假设我有两个c++类:
class A
{
public:
A() { fn(); }
virtual void fn() { _n = 1; }
int getn() { return _n; }
protected:
int _n;
};
class B : public A
{
public:
B() : A() {}
virtual void fn() { _n = 2; }
};
如果我写下面的代码:
int main()
{
B b;
int n = b.getn();
}
有人可能认为n被设为2。
结果是n被设为1。为什么?
正如已经指出的那样,对象是在构造时创建的。在构造基对象时,派生对象还不存在,因此虚函数重写不能工作。
然而,如果你的getter返回常量,这可以用多态getter来解决,多态getter使用静态多态性而不是虚函数,或者可以在静态成员函数中表示。本例使用CRTP (https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern)。
template<typename DerivedClass>
class Base
{
public:
inline Base() :
foo(DerivedClass::getFoo())
{}
inline int fooSq() {
return foo * foo;
}
const int foo;
};
class A : public Base<A>
{
public:
inline static int getFoo() { return 1; }
};
class B : public Base<B>
{
public:
inline static int getFoo() { return 2; }
};
class C : public Base<C>
{
public:
inline static int getFoo() { return 3; }
};
int main()
{
A a;
B b;
C c;
std::cout << a.fooSq() << ", " << b.fooSq() << ", " << c.fooSq() << std::endl;
return 0;
}
通过使用静态多态性,基类知道在编译时提供信息时调用哪个类的getter。
我刚刚在一个程序中出现了这个错误。
我有这样的想法:如果方法在构造函数中被标记为纯虚函数会发生什么?
class Base {
public:
virtual int getInt() = 0;
Base(){
printf("int=%d\n", getInt());
}
};
class Derived : public Base {
public:
virtual int getInt() override {return 1;}
};
和…有趣的事情!你首先得到编译器的警告:
warning: pure virtual ‘virtual int Base::getInt() const’ called from constructor
和一个来自ld的错误!
/usr/bin/ld: /tmp/ccsaJnuH.o: in function `Base::Base()':
main.cpp:(.text._ZN4BaseC2Ev[_ZN4BaseC5Ev]+0x26): undefined reference to `Base::getInt()'
collect2: error: ld returned 1 exit status
这是完全不合逻辑的,你只得到一个警告从编译器!