首页 > c++中与继承和static相关的一些问题

c++中与继承和static相关的一些问题

#include <iostream>

using namespace std;
class A
{
public:
    static int a;
    int b = 1;
    void test()
    {
        cout << "called A\n";
    }
};
int A::a = 10;

class B : public A
{
public:
    void test()
    {
        cout << "called B\n";
    }
};
int main()
{
    cout << B::a << endl;
    B* ptr_B = new B();
    ptr_B -> test();
    A* ptr_A = (A*)ptr_B;
    ptr_A -> test();
    cout << ptr_A << ' ' << ptr_B << endl;
    return 0;
}

代码如上,自己有几个地方比较困惑。
1.为什么static变量不能就地初始化,c++11不是就已经允许其它变量可以就地初始化吗?
2.当实例化派生类的时候,调用了基类的构造函数,那是相当于有一个匿名的基类对象被构造了吗?还是不存在这样的一个匿名对象,只是基类构造的部分是作为派生类的一部分而存在的?
3.用派生类的指针和基类的指针,当它们都是指向派生类对象的地址的时候,调用同名函数,它们的底层机制是如何实现的?为什么即便指向的是相同的地址,但是它们调用的时候却可以调用不同的函数?编译器层面是如何解释的哦?


1.只有成员变量和 static 的 const 的变量还有 enum 可以就地初始化,之所以 non-static 的不能够就地初始化,按照 Bjarne Stroustrup 的话来说就是:

A class is typically declared in a header file and a header file is
typically included into many translation units. However, to avoid
complicated linker rules, C++ requires that every object has a unique
definition.
That rule would be broken if C++ allowed in-class
definition of entities that needed to be stored in memory as objects.

2.作为派生类实例的一部分。
3.这个要分虚函数和非虚函数来考虑,你这里的test()是非虚函数,所以不会查找 v-table,按照变量的类型定义来查找对应实现;如果是virtual方法则会按照对象实际的类的对应方法。编译器层面对于你这里的例子而言,单纯的就是相当于std::bind(&B::test, ptr_B)();std::bind(&A::test, ptr_A)();,所以函数实现当然是不同的了。


1, C++11以后static成员可以直接初始化,但是仅限于字面量类型(literal type).
2, 准确的说,是属于基类的成员被初始化,并非匿名,而且这些成员也是派生类的一部分。
3, 这个问题比较大,你可以去了解一下C++的对象内存模型和virtual function的调用机制是怎样的,我可以简单的和你介绍一下:
(1) 带有虚函数里类里有一个隐秘的指针成员(vptr),它指向程序里的一块只读区域里的一张虚表(vtable)。
(2) 带有虚函数的类经过编译后都会有一张对应的虚表。
(3) 这个表里存了实际上这个类里虚函数的实现的函数地址。
(4) 当你调用一个对象的虚函数时,程序就会从它的vptr指向的vtable来找到实际上应当调用的函数。

【热门文章】
【热门文章】