【发布时间】:2009-12-21 00:01:57
【问题描述】:
我正在尝试确定当一个对象具有一些不会改变的特征并且在其整个功能中都需要时,最佳选择是什么。
- 静态常量成员
- Const 成员
在我看来,静态成员的真正原因是拥有一个可以更改的变量,从而影响同一类的所有其他对象。但是,我有人推荐类“不变量”是静态常量成员。我正在寻找有关建立类常量的推荐方法及其原因的一些见解。
【问题讨论】:
标签: c++
我正在尝试确定当一个对象具有一些不会改变的特征并且在其整个功能中都需要时,最佳选择是什么。
在我看来,静态成员的真正原因是拥有一个可以更改的变量,从而影响同一类的所有其他对象。但是,我有人推荐类“不变量”是静态常量成员。我正在寻找有关建立类常量的推荐方法及其原因的一些见解。
【问题讨论】:
标签: c++
const 成员应在该成员不基于每个实例更改时使用。 static const 成员应在该成员不按类更改时使用。换句话说,无论您创建多少个实例,static const 成员在所有实例之间保持固定,而 const 成员仅对于特定实例是恒定的。
我不确定这是否是您要查找的内容,因为这只是对它们行为方式的解释,但我希望它有所帮助。
【讨论】:
“不会改变”不够精确。这里的主要问题是类的不同对象是否需要具有这些 const 成员的不同值(即使它们在对象的生命周期内不会改变),还是所有对象都应该使用(共享)相同的值。
如果类的所有对象的值都相同,那么它当然应该是类的static const 成员。
如果不同的对象可能需要不同的值,那么它应该只是一个非静态的const 成员。
【讨论】:
static const。非静态 const 也可以(除了一些特定/特殊情况),但会导致完全不必要的内存浪费。
一个原因是常规的 const 成员会占用更多内存...即,对于您创建的类的每个对象,一个 const 成员对象将包含在该对象中并被初始化。
另一方面,如果它是静态 const 成员,那么无论您创建多少类的对象,都只会创建和初始化一个对象,并且所有类对象都将共享同一个对象。
为了演示,尝试两种方式编译它,创建几个对象,然后执行 printf("%p", &theConstMemberObject)... 当它是静态的时,你会看到它们都打印相同的指针值;当它不是静态的时,它们每个都有自己的对象,因此它们每个都打印不同的指针值。
【讨论】:
您将创建一个成员变量 static const,因为它不变,您可以重用它的相同副本,由您的类的所有实例共享。与每个实例都有自己的(相同的)常量值副本相反。
您会期望编译器足够聪明,可以为您执行此优化,我怀疑确实如此。不过,这是一个很好的习惯。
【讨论】:
我的偏好是不使用static const 成员,因为它似乎总是比const 成员产生更多的耦合;有时会混淆 w.r.t 菱形继承层次结构,其中最终类继承自 2 个超类(1 个类继承 public;另一个继承 virtual public)然后定义一个 static const 成员,该成员通过 new 指向动态内存区域、malloc、calloc 等会导致 double free 错误。
例如这是一个简单的钻石继承情况的输出
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;
}
【讨论】:
const 与static const 会在哪里产生影响。从您给出的描述来看,这听起来更像是static 与non-static 动态内存分配和删除的问题。
const 和static const 与多重/虚拟继承混合