我正在尝试确定当一个对象具有一些不会改变的特征时,最佳选择是什么,并且在整个函数中都需要它。
在我看来,静态成员的真正原因是拥有一个可以更改的变量,从而影响同一个类的所有其他对象。但是,我有人建议将类“不变量”作为静态const成员。我正在寻找有关建立类常量的推荐方法的一些见解,以及原因。
答案 0 :(得分:16)
“不会改变”不够精确。这里的主要问题是类的不同对象是否需要具有这些const成员的不同值(即使它们在对象的生命周期内没有改变),或者所有对象都应该使用(共享)相同的值。
如果该类的所有对象的值相同,那么它当然应该是该类的static const
成员。
如果不同的对象可能需要不同的值,那么它应该只是一个非静态const
成员。
答案 1 :(得分:14)
当该成员未按实例更改时,应使用const
成员。当该成员不按类别更改时,应使用static const
成员。换句话说,无论您创建多少个实例,static const
成员在所有实例之间保持固定,而const
成员仅对特定实例保持不变。
我不确定这是不是你要找的东西,因为这只是对它们行为方式的解释,但我希望它有所帮助。
答案 2 :(得分:1)
一个原因是常规const成员将占用更多内存...即,对于您创建的类的每个对象,一个const成员对象将包含在该对象中并初始化。
另一方面,如果它是一个静态const成员,那么无论您创建的类的对象有多少,都只会创建和初始化一个对象,并且所有类对象将共享同一个对象。
为了演示,尝试两种方式编译,创建多个对象,并执行printf(“%p”,& theConstMemberObject)......当它是静态的时,你会看到它们都打印相同的指针值;当它不是静态时,它们每个都有自己的对象,因此它们每个都会打印不同的指针值。
答案 3 :(得分:0)
您可以将成员变量设为static const,因为在它不变的情况下,您可以重复使用它的所有实例共享的相同副本。而不是每个实例都有自己的(相同的)常量值副本。
你会期望编译器足够聪明,可以为你做这个优化,我怀疑它确实如此。这是一个很好的习惯。
答案 4 :(得分:0)
我的偏好是不使用static const
成员,因为它似乎总是创建比const
成员更多的耦合;有时混淆钻石继承层次结构,其中最终类继承自2个超类(1个类继承public
;另一个继承virtual public
)然后定义指向动态的static const
成员通过new
,malloc
,calloc
等内存区域会导致double free
错误。
e.g。这是一个简单的钻石继承情况的输出
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$
以下是代码:
#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;
}