一、实现一个不能被继承的类
- 实现一个不能被继承的类有两种方法,下面我们一一来解释:
1、在C++98中我们可以将基类构造函数私有化,派生类调不到基类的构造函数,则无法继承。
#include <iostream>
using namespace std;
class Person
{
public:
static Person GetPerson()
{
return Person();
}
private:
Person()
{}
int _a;
};
class Student : public Person
{
private:
int _b;
};
int main()
{
Student s;
return 0;
}
这里我们可以看到运行之后编译器的提示是无法访问基类的私有成员,因为我们将基类的构造函数私有化,而我们在创建一个派生类对象时,必须调用父类的构造函数对父类成员进行初始化,而父类的私有成员在子类是不可见的,因此无法调用,这是Person就是一个无法被继承的类。
也许有人会说,那我把Person类的构造函数私有化了,在类外也不能调Person类的构造函数创建Person类的对象了,那Person不就是个没有用的类了,这里我们给了一个接口是static Person GetPerson()
我们在创建Person类对象时可以通过该接口调用类的构造函数初始化对象。
2、在C++11中给出了一个新的 关键字final来禁止继承
class Person final
{
private:
int _a;
};
class Student : class Person
{
private:
int _b;
};
我们将加上关键字final的类称为最终类,此类不能被继承
二、多继承中指针偏移问题
class Base1 {
public:
int _b1;
};
class Base2 {
public:
int _b2;
};
class Derive : public Base1, public Base2 {
public:
int _d;
};
int main()
{
Derive d;
Base1* p1 = &d;
Base2* p2 = &d;
Derive* p3 = &d;
return 0;
}
这里有四个选项
- A. p1 == p2 == p3
- B. p1 < p2 < p3
- C. p1 == p3 != p2
- D. p1 != p2 != p3
如下图所示,我们可以清楚的看到p1指针和p3指针是相同的,虽然它们的含义不一样,但是在值上是相同的。
三、计算一个类的大小
1、仅有一个类的情况
class Base
{
public:
virtual void Func1()
{
cout << "Func1()" << endl;
}
void Func2()
{
cout << "Func2" << endl;
}
private:
int _b = 1;
};
int main()
{
printf("%d\n", sizeof(Base));//8个字节
return 0;
}
在32位系统下,是8个字节,因为32位系统下指针是4个字节,而Base类中有一个int型对象和一个虚基表指针详情参见博客 多态(下)之多态的实现原理
若是在64位系统下指针是8个字节,此时Base类的大小为12 字节。
2、有基类和派生类的情况
class Base
{
public:
virtual void Func1()
{
cout << "Base::Func1()" << endl;
}
virtual void Func2()
{
cout << "Base::Func2()" << endl;
}
void Func3()
{
cout << "Base::Func3()" << endl;
}
private:
int _b = 1;
};
class Derive : public Base
{
public:
virtual void Func1()
{
cout << "Derive::Func1()" << endl;
}
private:
int _d = 2;
};
int main()
{
Base b;
Derive d;
printf("Base:%d\n", sizeof(Base));
printf("Derive:%d\n", sizeof(Derive));
return 0;
}