剑指offer 48---设计一个类不能被继承

36 篇文章 1 订阅
25 篇文章 0 订阅

设计一个类不能被继承

在C++继承中,子类的构造函数会自动调用父类的构造,子类的析构会自动调用父类的析构。

一个简单的例子:

class AA
{
public:
	AA()
	{
		cout << "AA()" << endl;
	}
	~AA()
	{
		cout << "~AA()" << endl;
	}
};

class BB:public AA
{
public:
	BB()
	{
		cout << "BB()" << endl;
	}
	~BB()
	{
		cout << "~BB()" << endl;
	}
};
int main()
{
	BB tty;
	return 0;
}



由上述可见,那是不是将父类的构造,析构都定义为私有就可以了呢?

解一:将父类的构造,析构都定义为私有,要求:父类单独作为一个类,必须可以正常使用

           很明显,一个类的构造,析构均为私有,在类外是无法生成对象的,所以需要使用静态成员函数

class AA
{
public:
	static AA* Typ()
	{
		AA* p = new AA;    //创建对象
		cout << "static AA* Typ" << endl;
		return p;
	}
	static void Delete(AA* qqw)
	{
		cout << "static void Delete" << endl;
		delete qqw;      //清理空间
		qqw = NULL;
	}
private:
	AA()
	{
		cout << "AA()" << endl;
	}
	~AA()
	{
		cout << "~AA()" << endl;
	}
};
int main()
{
	AA *tty = AA::Typ();   //在堆上创建对象
	//BB qp;
	return 0;
}



PS:

此时构建的AA类是符合条件的,可以单独编译,可以正常使用。

此时的类不能被继承,因为其构造,析构是私有的。

缺陷:

1.使用不方便,静态成员函数需要使用类型::作用域访问符直接调用静态成员函数

2.由静态成员函数创建的对象只能得到在堆上的实例,无法得到在栈上的实例。

3.静态成员函数不能被继承


优化:解2:利用虚继承(利用的是友元的特性,使得BB可以访问AA 的私有成员)

template<class T>
class AA
{
public:
	friend T;
private:
	AA()
	{
		cout << "AA()" << endl;
	}
	~AA()
	{
		cout << "~AA()" << endl;
	}
};

class BB:virtual public AA<BB>   //此时BB是AA的友元,可以访问AA中的任何成员
{
public:
	BB()
	{
		cout << "BB()" << endl;
	}
	
	~BB()
	{
		cout << "~BB()" << endl;
	}
};
int main()
{
	BB* p = new BB;   //在堆上创建对象
	BB tty;    //在栈上创建对象
	return 0;
}


因为BB是AA的友元,所以,它可以访问父类的私有成员,构造,析构,所以可以创建对象,编译正确。

可以在堆上创建对象,也可以在栈上创建对象。

那能否继承呢?当在写一个类去继承BB 时,无法编译

子类在构造对象时,因为是虚继承,所以子类的构造函数会直接去调用父类的构造函数,而AA的构造函数是私有的。运行错误error!!!

这就是一个真正不能被继承的类。


友元的特性:
1.友元关系是单向的,不具有交换性。若类B是类A的友元,类A不一定是类B的友元,要看在类中是否有相应的声明。

2.友元关系不具有传递性。若类B是类A的友元,类C是B的友元,类C不一定是类A的友元,同样要看类中是否有相应的申明

3.友元关系不能继承,基类的友元对派生类的成员没有特殊的访问权限。如果基类被授予友元关系,则只有基类具有特殊的访问权限。该基类的派生类不能访问授予友元关系的类。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值