更多c++知识:c++目录索引
1. 实现一个不能被继承的类
思路:
子类继承父类,子类的构造函数就是合成的;当子类创建对象时,先调用父类的构造函数,在调用自己的构造函数,故此不能继承,将父类的构造函数设为私有成员,这样子类就不能访问,不能创建对象,因此也就不能继承
代码:
class AA
{
public:
static AA* GetObject()
{
return new AA;//直接new一个AA对象
}
/*static AA GetObject()
{
return AA();//调用拷贝构造,返回一个匿名对象
}*/
private:
AA()
{}
int _a;
};
class BB :public AA
{
protected:
int _b;
};
int main()
{
BB bb;
system("pause");
return 0;
}
2. 实现一个类,定义的对象都在堆上
思路:
沿用上一题的思路,将拷贝构造定义成私有成员,只提供创建对象在堆上的接口
代码一:
class AA
{
public:
static AA* GetObject()
{
return new AA;
}
private:
AA()
{}
int _a;
};
分析:上面代码可以实现将对象创建在堆上,但不可避免的是创建的对象也可以在栈上;拷贝构造不是私有成员,当我们利用拷贝构造时,就可将对象创建在栈上,例如:
AA* aa=AA::GetObject();
AA aa1(*aa);//利用拷贝构造出来的对象在栈上
AA aa2 = *aa;
system("pause");
return 0;
解决办法:
既然会利用拷贝构造创建出在栈上的对象,因此我们可对拷贝构造作两件事情,并且二者缺一不可:
将拷贝构造定义成私有成员
只声明拷贝构造,但不实现拷贝构造
关于上述的两个条件,通过下面代码来验证:
代码1:公有成员,只声明拷贝构造,但不实现拷贝构造
class AA
{
public:
static AA* GetObject()
{
return new AA;
}
AA(const AA& aa);
private:
AA()
{}
int _a;
};
AA::AA(const AA& aa)
{
cout << "AA(const AA& aa)" << endl;
}
int main()
{
AA* aa=AA::GetObject();
AA aa1(*aa);//利用拷贝构造出来的对象在栈上
AA aa2 = *aa;
system("pause");
return 0;
}
结果分析:虽然在类里没有实现拷贝构造,但突破类域,我们依然可以实现,此时调用拷贝构造,创建的对象依旧在栈上
代码2:只声明不实现的拷贝构造为私有成员
class AA
{
public:
static AA* GetObject()
{
return new AA;
}
private:
AA()
{}
AA(const AA& aa);
AA& operator=(const AA& aa);
int _a;
};
int main()
{
AA* aa=AA::GetObject();
AA aa1(*aa);//利用拷贝构造出来的对象在栈上
AA aa2 = *aa;
system("pause");
return 0;
}
结果分析:将拷贝构造声明为私有成员,并且不实现,此时在类外面调不动私有成员,只能通过创建对象接口来构造对象,并且构造的对象的堆上
3. 实现一个类,创建的对象只能在栈上
思路:
和上题的思路一样,将构造封装成私有成员,提供构造对象的接口
代码:
class AA
{
public:
static AA GetObject()
{
return AA();
}
private:
int _a;
};
int main()
{
AA aa = AA::GetObject();
system("pause");
return 0;
}
4. 实现一个类,定义的对象不能在堆上
思路:
在堆上定义对象,无非是通过new和delete来完成,故此我们将new和delete两个操作符都封装成私有成员,并且不实现,即可达到目的
代码:
class AA
{
public:
AA()
{}
private:
void* operator new(size_t size);
void operator delete(void* p);
int _a;
};
int main()
{
AA aa;
AA* p = new AA;
system("pause");
return 0;
}
结果: