2009-12-21 35 views
8

Tôi đang cố gắng quyết định lựa chọn nào tốt nhất khi đối tượng có một số đặc điểm không thay đổi và cần thiết trong suốt các chức năng của nó.Thành viên riêng: Tĩnh const so với chỉ const

  1. thành viên const tĩnh
  2. thành viên Const

Dường như với tôi như lý do thực sự cho một thành viên tĩnh là phải có một biến mà có thể thay đổi, và do đó ảnh hưởng đến tất cả các đối tượng khác của cùng lớp. Tuy nhiên, tôi đã có người đề nghị lớp "bất biến" là thành viên const tĩnh. Tôi đang tìm một số thông tin chi tiết về cách tiếp cận được đề xuất để thiết lập các hằng số lớp học và lý do tại sao.

Trả lời

15

"Không thay đổi" không đủ chính xác. Câu hỏi chính ở đây là liệu các đối tượng khác nhau của lớp có cần phải có các giá trị khác nhau của các thành viên const này (ngay cả khi chúng không thay đổi trong suốt thời gian của đối tượng) hoặc tất cả các đối tượng nên sử dụng (chia sẻ) cùng giá trị.

Nếu giá trị giống nhau cho tất cả các đối tượng của lớp, thì tất nhiên, nó phải là thành viên static const của lớp học.

Nếu các đối tượng khác nhau có thể yêu cầu các giá trị khác nhau, thì đó chỉ là thành viên không tĩnh const.

+0

Bằng "sẽ không thay đổi" Tôi có nghĩa là giá trị là như nhau cho tất cả các đối tượng của lớp. – trikker

+3

Trong trường hợp đó bạn không có lý do gì để không làm cho nó trở thành 'static const'. Một const không tĩnh sẽ làm việc tốt (ngoài một số trường hợp cụ thể/kỳ lạ), nhưng nó sẽ dẫn đến sự lãng phí không cần thiết của bộ nhớ. – AnT

+0

Vâng, đó là ý chính của tôi. – trikker

14

Thành viên const nên được sử dụng khi thành viên đó không thay đổi trên cơ sở từng trường hợp. Thành viên static const nên được sử dụng khi thành viên đó không thay đổi trên cơ sở mỗi lớp. Nói cách khác, không có vấn đề bao nhiêu trường hợp bạn tạo ra, các thành viên static const vẫn cố định giữa tất cả các trường hợp trong khi các thành viên const là hằng số chỉ cho một trường hợp cụ thể.

Tôi không chắc đó có phải là những gì bạn đang tìm kiếm vì đó chỉ là lời giải thích về cách chúng cư xử, nhưng tôi hy vọng nó sẽ giúp ích một chút.

+0

Giải thích chính xác. –

1

Một lý do là các thành viên const thông thường sẽ chiếm nhiều bộ nhớ hơn ... tức là đối với từng đối tượng của lớp bạn tạo, một đối tượng thành viên const sẽ được bao gồm trong đối tượng đó và được khởi tạo.

Nếu đó là thành viên const tĩnh, thì chỉ một đối tượng sẽ được tạo và khởi tạo, bất kể bạn tạo bao nhiêu đối tượng và tất cả đối tượng lớp sẽ chia sẻ cùng một đối tượng.

Để minh họa, hãy thử biên dịch cả hai cách, tạo một vài đối tượng và thực hiện printf ("% p", & theConstMemberObject) ... khi tĩnh, bạn sẽ thấy tất cả đều in cùng giá trị con trỏ; khi nó không phải là tĩnh, mỗi người đều có đối tượng riêng của họ và do đó họ từng in một giá trị con trỏ khác nhau.

0

Bạn sẽ tạo thành const tĩnh biến thành viên bởi vì, nó không thay đổi, bạn có thể tái sử dụng cùng một bản sao của nó, được chia sẻ bởi tất cả các phiên bản của lớp của bạn. Trái ngược với mỗi trường hợp có bản sao riêng (giống hệt) của giá trị không đổi.

Bạn có thể mong đợi trình biên dịch đủ thông minh để thực hiện việc tối ưu hóa này cho bạn, và tôi nghi ngờ điều đó xảy ra. Đó là một thói quen tốt đẹp để có được vào mặc dù.

+2

Biến thành viên const có thể được khởi tạo trong hàm tạo nên có thể thay đổi đối với các phiên bản khác nhau của lớp. – danio

+1

Bạn phải cẩn thận với những gì bạn có thể giả định trình biên dịch để làm cho bạn. Như @danio chỉ ra, nếu tiêu đề được tái sử dụng trong các đơn vị biên dịch khác nhau, chỉ có một đơn vị biên dịch nơi trình biên dịch có thể biết rằng giá trị được chia sẻ, trái ngược với nhiều giá trị phải xác định bố cục bộ nhớ tương thích. Một trong những người biết, không thể thay đổi bố trí bộ nhớ vì nó sẽ phá vỡ mã trong tất cả các đơn vị biên dịch khác. –

0

tùy chọn của tôi không được sử dụng static const thành viên vì dường như nó luôn tạo ra nhiều khớp nối hơn const thành viên; đôi khi nhầm lẫn w.r.t phân cấp thừa kế kim cương mà lớp cuối cùng kế thừa từ 2 lớp siêu (lớp 1 được thừa hưởng public; lớp kia được thừa hưởng virtual public), sau đó xác định thành viên static const trỏ đến vùng bộ nhớ động qua new, malloc, calloc v.v. sẽ dẫn đến double free lỗi.

ví dụ: đây là sản phẩm của một tình huống đơn giản thừa kế kim cương

ray:~ ray$ ./multiinheritance 
Base() called 
Derived1() called 
Base() called 
Derived2() called 
Final() called 
~Final() called 
~Derived2() called 
~Base() called 
freeing memory 
~Derived1() called 
~Base() called 
freeing memory 
multiinheritance(475) malloc: *** error for object 0x100150: double free 
*** set a breakpoint in malloc_error_break to debug 
ray:~ ray$ 

Dưới đây là các mã:

#include <iostream> 
#include <string> 

class Base { 
public: 
    Base() { 
     std::cout << "Base() called " << std::endl; 
    } 
    virtual ~Base() { 
     std::cout << "~Base() called" << std::endl; 
     std::cout << "freeing memory" << std::endl; 
     delete i; 
    } 
    static const int* i; 
}; 

const int* Base::i = new int[5]; 

class Derived1 : virtual public Base { 
public: 
    Derived1() { 
     std::cout << "Derived1() called " << std::endl; 
    } 
    virtual ~Derived1() { 
     std::cout << "~Derived1() called" << std::endl; 
    } 
}; 
class Derived2 : public Base { 
public: 
    Derived2() { 
     std::cout << "Derived2() called " << std::endl; 
    } 
    virtual ~Derived2() { 
     std::cout << "~Derived2() called" << std::endl; 
    } 
}; 

class Final: public Derived1, public Derived2 { 
public: 
    Final() { 
     std::cout << "Final() called" << std::endl; 
    } 
    ~Final() { 
     std::cout << "~Final() called" << std::endl; 
    } 
}; 

int main(int argc, char** argv) { 
    Final f; 
return 0; 
} 
+0

Bạn nên đăng mã mà từ đó bạn nhận được kết quả đó, nếu không nó sẽ vô ích. Và tôi không chắc chắn nó sẽ hữu ích anyway, như tôi không thấy nơi 'const' vs' static const' sẽ làm cho một sự khác biệt. Từ mô tả, bạn cho nó có vẻ giống như một vấn đề với việc phân bổ và xóa bộ nhớ động 'tĩnh' so với' không tĩnh '. –

+0

@dribeas, tôi đã cố gắng minh họa rằng đôi khi trộn 'const' và' static const' với nhiều thừa kế/ảo –

Các vấn đề liên quan