Từ 1 tới 8 trên tổng số 8 kết quả

Đề tài: [ Solved ]Có phải là sai về Static ko ?? Cứu với

  1. #1
    Ngày gia nhập
    03 2008
    Bài viết
    0

    Wink [ Solved ]Có phải là sai về Static ko ?? Cứu với

    C++ Code:
    1. #include"iostream.h"
    2. typedef int datatype;
    3. class vector{
    4.     datatype* dataarray;
    5.     static datatype numvector;
    6.     static void vectornum(){
    7.         numvector=0;       
    8.         do{
    9.             cout<<"So vector cua truong:(Khong qua 3)";cin>>numvector;
    10.         }
    11.         while(numvector>3||numvector==0);
    12.     }      
    13. public:
    14.     vector(){
    15.         vectornum();       
    16.         dataarray=new datatype[numvector];
    17.         for(int i=0;i<numvector;i++)
    18.             dataarray[i]=0;
    19.     }
    20.     ~vector(){
    21.         if(dataarray!=NULL)
    22.             delete []dataarray;
    23.     }
    24.     void display() const{
    25.         for(int i=0;i<numvector;i++)
    26.             cout<<dataarray[i]<<" ";
    27.     }  
    28. };
    29. void main(){   
    30.     vector a;
    31.     a.display();   
    32. }

    em đang xài visual C++ biên dịch thì hiện ra 2 lỗi :
    unresolved external symbol "private: static int vector::numvector" (?numvector@vector@@0HA)

    Em không hiểu vì sao lại sai lõi này nữa ?? Em nghĩ có lẽ là do em nhập dữ liệu trong hàm static?? không biết em hiểu đúng ko mấy bác nhỉ

  2. #2
    Ngày gia nhập
    12 2006
    Nơi ở
    US
    Bài viết
    1,917

    static data member là 1 thằng dành cho 1 class, làm sao cậu có thể truy xuất kiểu quái lạ đó được ?
    C++ Code:
    1. vector(){
    2.         vectornum();       
    3.         dataarray=new datatype[numvector];
    4.         for(int i=0;i<numvector;i++)
    5.             dataarray[i]=0;
    6.     }
    Chỗ này constructor, nói với compiler rằng mỗi lần tau khởi tạo 1 object thì làm ơn gọi thằng static ra đây : -> static nói lại rằng tau là cho cả class chứ ko dành riêng cho mày !!!

  3. #3
    Ngày gia nhập
    10 2007
    Nơi ở
    Gameloft studio
    Bài viết
    175

    Bạn đọc bài viết này thử xem có hiểu vấn đề rok_rook nói không nha

    CÁC THÀNH VIÊN TĨNH CỦA LỚP

    Bình thường, mỗi đối tượng của một lớp có bản sao chép của chính nó của tất cả các thành viên dữ liệu của lớp. Trong các trường hợp nhất định chỉ có duy nhất một bản chép thành viên dữ liệu đặc biệt cần phải dùng chung bởi tất cả các đối tượng của một lớp. Một thành viên dữ liệu tĩnh được sử dụng cho những điều đó và các lý do khác. Một thành viên dữ liệu tĩnh biểu diễn thông tin toàn lớp (class-wide). Khai báo một thành viên tĩnh bắt đầu với từ khóa static.

    Mặc dù các thành viên dữ liệu tĩnh có thể giống như các biến toàn cục, các thành viên dữ liệu tĩnh có phạm vi lớp. Các thành viên tĩnh có thể là public, private hoặc protected. Các thành viên dữ liệu tĩnh phải được khởi tạo một lần (và chỉ một lần) tại phạm vi file. Các thành viên lớp tĩnh public có thể được truy cập thông qua bất kỳ đối tượng nào của lớp đó, hoặc chúng có thể được truy cập thông qua tên lớp sử dụng toán tử định phạm vi. Các thành viên lớp tĩnh private và protected phải được truy cập thông qua các hàm thành viên public của lớp hoặc thông qua các friend của lớp. Các thành viên lớp tĩnh tồn tại ngay cả khi đối tượng của lớp đó không tồn tại. Để truy cập một thành viên lớp tĩnh public khi các đối tượng của lớp không tồn tại, đơn giản thêm vào đầu tên lớp và toán tử định phạm vi cho thành viên dữ liệu. Để truy cập một thành viên lớp tĩnh private hoặc protected khi các đối tượng của lớp không tồn tại, một hàm thành viên public phải được cung cấp và hàm phải được gọi bởi thêm vào đầu tên của nó với tên lớp và toán tử định phạm vi.

    Ví dụ 3.19: Chương trình sau minh họa việc sử dụng thành viên dữ liệu tĩnh private và một hàm thành viên tĩnh public.
    C++ Code:
    1.  
    2.  CT3_19.CPP  
    3.  1: #include <iostream.h>
    4.  
    5. 2: #include <string.h>
    6.  
    7. 3: #include <assert.h>
    8.  
    9. 4:
    10.  
    11. 5: class Employee
    12.  
    13. 6: {
    14.  
    15. 7: public:
    16.  
    17. 8: Employee(const char*, const char*); // Constructor
    18.  
    19. 9: ~Employee(); // Destructor
    20.  
    21. 10: char *GetFirstName() const; // Trả về first name
    22.  
    23. 11: char *GetLastName() const; // Trả về last name
    24.  
    25. 12: // Hàm thành viên tĩnh
    26.  
    27. 13: static int GetCount(); // Trả về số đối tượng khởi tạo
    28.  
    29. 14: private:
    30.  
    31. 15: char *FirstName;
    32.  
    33. 16: char *LastName;
    34.  
    35. 17: // static data member
    36.  
    37. 18: static int Count; // Số đối tượng khởi tạo
    38.  
    39. 19: };
    40.  
    41. 20:
    42.  
    43. 21: // Khởi tạo thành viên dữ liệu tĩnh
    44.  
    45. 22: int Employee::Count = 0;
    46.  
    47. 23:
    48.  
    49. 24: // Định nghĩa hàm thành viên tỉnh mà trả về số đối tượng khởi tạo
    50.  
    51. 25: int Employee::GetCount()
    52.  
    53. 26: {
    54.  
    55. 27: return Count;
    56.  
    57. 28: }
    58.  
    59. 29:
    60.  
    61. 30: // Constructor cấp phát động cho first name và last name
    62.  
    63. 31: Employee::Employee(const char *First, const char *Last)
    64.  
    65. 32: {
    66.  
    67. 33: FirstName = new char[ strlen(First) + 1 ];
    68.  
    69. 34: assert(FirstName != 0); // Bảo đảm vùng nhớ được cấp phát
    70.  
    71. 35: strcpy(FirstName, First);
    72.  
    73. 36: LastName = new char[ strlen(Last) + 1 ];
    74.  
    75. 37: assert(LastName != 0); // Bảo đảm vùng nhớ được cấp phát
    76.  
    77. 38: strcpy(LastName, Last);
    78.  
    79. 39: ++Count; // Tăng số đối tượng lên 1
    80.  
    81. 40: cout << "Employee constructor for " << FirstName
    82.  
    83. 41:       << ' ' << LastName << " called." << endl;
    84.  
    85. 42: }
    86.  
    87. 43:
    88.  
    89. 44: // Destructor giải phóng vùng nhớ đã cấp phát
    90.  
    91. 45: Employee::~Employee()
    92.  
    93. 46: {
    94.  
    95. 47: cout << "~Employee() called for " << FirstName
    96.  
    97. 48:       << ' ' << LastName << endl;
    98.  
    99. 49: delete FirstName;
    100.  
    101. 50: delete LastName;
    102.  
    103. 51: --Count; // Giảm số đối tượng xuống 1
    104.  
    105. 52: }
    106.  
    107. 53:
    108.  
    109. 54: // Trả về first name
    110.  
    111. 55: char *Employee::GetFirstName() const
    112.  
    113. 56: {
    114.  
    115. 57: char *TempPtr = new char[strlen(FirstName) + 1];
    116.  
    117. 58: assert(TempPtr != 0); // Bảo đảm vùng nhớ được cấp phát
    118.  
    119. 59: strcpy(TempPtr, FirstName);
    120.  
    121. 60: return TempPtr;
    122.  
    123. 61: }
    124.  
    125. 62:
    126.  
    127. 63: // Trả về last name
    128.  
    129. 64: char *Employee::GetLastName() const
    130.  
    131. 65: {
    132.  
    133. 66: char *TempPtr = new char[strlen(LastName) + 1];
    134.  
    135. 67: assert(TempPtr != 0); // Bảo đảm vùng nhớ được cấp phát
    136.  
    137. 68: strcpy(TempPtr, LastName);
    138.  
    139. 69: return TempPtr;
    140.  
    141. 70: }
    142.  
    143. 71:
    144.  
    145. 72: int main()
    146.  
    147. 73: {
    148.  
    149. 74: cout << "Number of employees before instantiation is "
    150.  
    151. 75:       << Employee::GetCount() << endl; // Sử dụng tên lớp
    152.  
    153. 76: Employee *E1Ptr = new Employee("Susan", "Baker");
    154.  
    155. 77: Employee *E2Ptr = new Employee("Robert", "Jones");
    156.  
    157. 78: cout << "Number of employees after instantiation is "
    158.  
    159. 79:       << E1Ptr->GetCount() << endl;
    160.  
    161. 80: cout << endl << "Employee 1: "
    162.  
    163. 81:       << E1Ptr->GetFirstName()
    164.  
    165. 82:       << " " << E1Ptr->GetLastName()
    166.  
    167. 83:       << endl << "Employee 2: "
    168.  
    169. 84:       << E2Ptr->GetFirstName()
    170.  
    171. 85:       << " " << E2Ptr->GetLastName() << endl << endl;
    172.  
    173. 86: delete E1Ptr;
    174.  
    175. 87: delete E2Ptr;
    176.  
    177. 88: cout << "Number of employees after deletion is "
    178.  
    179. 89:       << Employee::GetCount() << endl;
    180.  
    181. 90:    return 0;
    182.  
    183. 91: }

    Thành viên dữ liệu Count được khởi tạo là zero ở phạm vi file với lệnh:

    int Employee::Count = 0;

    Thành viên dữ liệu Count duy trì số các đối tượng của lớp Employee đã được khởi tạo. Khi đối tượng của lớp Employee tồn tại, thành viên Count có thể được tham chiếu thông qua bất kỳ hàm thành viên nào của một đối tượng Employee – trong ví dụ này, Count được tham chiếu bởi cả constructor lẫn destructor. Khi các đối tượng của lớp Employee không tồn tại, thành viên Count có thể vẫn được tham chiếu nhưng chỉ thông qua một lời gọi hàm thành viên tĩnh public GetCount() như sau:

    Employee::GetCount()

    Hàm GetCount() được sử dụng để xác định số các đối tượng của Employee khởi tạo hiện hành. Chú ý rằng khi không có các đối tượng trong chương trình, lời gọi hàm Employee::GetCount() được đưa ra. Tuy nhiên khi có các đối tượng khởi động hàm GetCount() có thể được gọi thông qua một trong các đối tượng như sau:

    E1Ptr->GetCount()

    Trong chương trình ở các dòng 34, 37, 58 và 67 sử dụng hàm assert() (định nghĩa trong assert.h). Hàm này kiểm tra giá trị của biểu thức. Nếu giá trị của biểu thức là 0 (false), hàm assert() in một thông báo lỗi và gọi hàm abort() (định nghĩa trong stdlib.h) để kết thúc chương trình thực thi. Nếu biểu thức có giá trị khác 0 (true) thì chương trình tiếp tục. Điều này rất có ích cho công cụ debug đối với việc kiểm tra nếu một biến có giá trị đúng. Chẳng hạn hàm ở dòng 34 hàm assert() kiểm tra con trỏ FirstName để xác định nếu nó không bằng 0 (null). Nếu điều kiện trong khẳng định (assertion) cho trước là đúng, chương trình tiếp tục mà không ngắt. Nếu điều kiện trong khẳng định cho trước là sai, một thông báo lỗi chứa số dòng, điều kiện được kiểm tra, và tên file trong đó sự khẳng định xuất hiện được in, và chương trình kết thúc. Khi đó lập trình viên có thể tập trung vào vùng này của đoạn mã để tìm lỗi.

    Các khẳng định không phải xóa từ chương trình khi debug xong. Khi các khẳng định không còn cần thiết cho mục đích debug trong một chương trình, dòng sau:

    #define NDEBUG

    được thêm vào ở đầu file chương trình. Điều này phát sinh tiền xử lý bỏ qua tất cả các khẳng định thay thế cho lập trình viên xóa mỗi khẳng định bằng tay.


    Chúng ta chạy ví dụ 3.19, kết quả ở hình 3.20



    Hình 3.20: Kết quả của ví dụ 3.19

    Một hàm thành viên có thể được khai báo là static nếu nó không truy cập đến các thành viên không tĩnh. Không giống như các thành viên không tĩnh, một hàm thành viên tĩnh không có con trỏ this bởi vì các thành viên dữ liệu tĩnh và các hàm thành viên tĩnh tồn tại độc lập với bất kỳ đối tượng nào của lớp.

    Chú ý: Hàm thành viên dữ liệu tĩnh không được là const.
    *Tham khảo tài liệu đào tạo từ xa của tác giả Vũ Thanh Hiền
    Không biết ghi gì luôn ...

  4. #4
    Ngày gia nhập
    12 2006
    Nơi ở
    US
    Bài viết
    1,917

    By the way, this is an example how to implement that correctly :
    C++ Code:
    1. #include <iostream>
    2. #include <fstream>
    3. #include <cstdlib>
    4.  
    5. template <typename T>
    6. class vector{
    7. private :
    8.     int size;
    9.     T* dataarray;
    10.  
    11. public:
    12.     vector():size(0), dataarray(new T()){}
    13.     ~vector();
    14.     void readin(std::istream &iss);
    15.     void display(std::ostream &oss) const;
    16.  
    17. };
    18.  
    19. template <typename T>
    20. vector<T>::~vector()
    21. {
    22.     if(dataarray!=NULL)
    23.         delete []dataarray;
    24.     else
    25.         std::cerr << "Error";
    26. }
    27.  
    28. template <typename T>
    29. void vector<T>::display(std::ostream &oss) const
    30. {
    31.     for(int i=0;i<size;i++)
    32.         oss<<dataarray[i]<<" ";
    33. }
    34.  
    35. template <typename T>
    36. void vector<T>::readin(std::istream &iss)
    37. {
    38.     iss >> size;
    39.     dataarray=new T[size];
    40. }
    41.  
    42. int main()
    43. {
    44.   vector<int> vect;
    45.   vect.readin(std::cin);
    46.   vect.display(std::cout);
    47. }

  5. #5
    Ngày gia nhập
    03 2008
    Bài viết
    0

    Củm ơn 2 bác ! Đúng là sai thật ! Em gà wá ! tại mới học về hướng đối tượng thoai !
    Em nói vậy xem có đúng không nha bác :
    Code:
    static void vectornum(){
    	numvector=0;		
    	do{
    		cout<<"So vector cua truong:(Khong qua 3)";cin>>numvector;
    	}
    	while(numvector>3||numvector==0);
    }
    Đoạn trên bị sai vì static đata là của chung của lớp , mà nếu làm như hàm trên thì mỗi lần khởi tạo lớp nó sẽ lấy static data ra yêu cầu nhập vào --> sai ! Đúng không bác nhỉ ??

    Nhưng mà còn đoạn này :
    Code:
    vector(){
            vectornum();       
            dataarray=new datatype[numvector];
            for(int i=0;i<numvector;i++)
                dataarray[i]=0;
    }
    Thì static data là của chung của lóp , nên ta có thể lấy dữ liệu của nó ra để so sánh hay làm j đó , miễn là không làm thay đổi dữ liệu của nó thoai ! Em nói vậy đúng không bác ?? Hiz hiz Em mới học hđtượng này xin các bác chỉ dạy thêm cho em

    ----------
    Nhắc nhở: trong nội quy của diễn đàn, không cho phép các bạn dùng ngôn ngữ chat như: các bác... Bạn nên xưng hô với từ ngữ khác hay hơn.
    Đã được chỉnh sửa lần cuối bởi Forlorn_hope : 16-03-2008 lúc 12:46 PM.

  6. #6
    Ngày gia nhập
    12 2006
    Nơi ở
    US
    Bài viết
    1,917

    Mặc định [ Solved ]Có phải là sai về Static ko ?? Cứu với

    I think you got it T_T, just remember this :
    Static means several things (two many for my taste). When applied to a free-standing function, it means that the name won't be visible outside of this translation unit. When applied to a member function, it means it doesn't actually get a pointer to an instance of the class as an implicit parameter. When applied to a local variable, it means that it's persistent (something like a global variable with local scope).

  7. #7
    Ngày gia nhập
    08 2006
    Nơi ở
    TpHCM
    Bài viết
    202

    Ngoài cái lỗi mà rox_rook nêu ra, lỗi chính của nó mà tui vẫn chưa thấy nói đến

    unresolved external symbol "private: static int vector::numvector" (?numvector@vector@@0HA)
    Bạn thêm đoạn này vào file cpp bất kỳ (có thể là main.cpp, nhưng phải đặt bên ngoài class vector)

    Code:
    datatype vector::numvector;
    void vector::vectornum(){
    		numvector=0;		
    		do{
    			cout<<"So vector cua truong:(Khong qua 3)";cin>>numvector;
    		}
    		while(numvector>3||numvector==0);
    	}
    hàm vectornum() ở trong class vector sửa lại, chỉ viết protype của hàm thôi
    Code:
    static void vector::vectornum();

  8. #8
    Ngày gia nhập
    12 2006
    Nơi ở
    US
    Bài viết
    1,917

    Nếu anh bỏ ra ngoài thì chẳng qua là cách nói thứ 2 của 1 vấn đề thôi mà ? Hơn nữa anh nhầm 1 chỗ rùi T_T :
    C++ Code:
    1. static void vector::vectornum();
    Làm sao anh bỏ scope vector:: trong class thế này được nhỉ
    C++ Code:
    1. #include <iostream>
    2. using std::cout;
    3. using std::cin;
    4.  
    5. typedef int datatype;
    6. class vector{
    7.     datatype* dataarray;
    8.     static datatype numvector;
    9. public:
    10.         static void vectornum();
    11.     vector(){
    12.                 dataarray=new datatype[numvector];
    13.         for(int i=0;i<numvector;i++)
    14.             dataarray[i]=0;
    15.     }
    16.     ~vector(){
    17.         if(dataarray!=NULL)
    18.             delete []dataarray;
    19.     }
    20.     void display() const{
    21.         for(int i=0;i<numvector;i++)
    22.             cout<<dataarray[i]<<" ";
    23.     }  
    24. };
    25.  
    26. datatype vector::numvector;
    27. void vector::vectornum()
    28. {
    29.         numvector=0;       
    30.         do{
    31.             cout<<"So vector cua truong:(Khong qua 3)";
    32.             cin>>numvector;
    33.         }
    34.         while(numvector>3||numvector==0);
    35. }
    36.        
    37.        
    38. int main(){
    39.         vector::vectornum();
    40.     vector a;
    41.     a.display();   
    42. }

Các đề tài tương tự

  1. Cách gọi hàm từ 1 Form khác mà hàm đó không phải là hàm static
    Gửi bởi michinin trong diễn đàn Thắc mắc lập trình C#
    Trả lời: 9
    Bài viết cuối: 03-10-2013, 10:26 AM
  2. Khai báo "Biến" trong lớp với từ khóa static, thì đó có phải là thuộc tính không?
    Gửi bởi phngcngtn trong diễn đàn Thắc mắc lập trình C#
    Trả lời: 4
    Bài viết cuối: 20-04-2012, 10:12 PM
  3. Cách sử dụng thành phần tĩnh(static) trong C#
    Gửi bởi svcntt trong diễn đàn Thắc mắc lập trình C#
    Trả lời: 9
    Bài viết cuối: 28-05-2011, 10:02 AM
  4. [Solved]Vấn đề với dấu phẩy động?
    Gửi bởi vuanhkhai trong diễn đàn Nhập môn lập trình C/C++
    Trả lời: 7
    Bài viết cuối: 25-10-2008, 10:42 AM
  5. [ Solved ]Ai biết static binding+dynamic binding ko?
    Gửi bởi forever_and_one trong diễn đàn Nhập môn lập trình C/C++
    Trả lời: 5
    Bài viết cuối: 31-08-2008, 11:13 PM

Quyền hạn của bạn

  • Bạn không thể gửi đề tài mới
  • Bạn không thể gửi bài trả lời
  • Bạn không thể gửi các đính kèm
  • Bạn không thể chỉnh sửa bài viết của bạn