1.如何实现一个不能被继承的类
不能被继承的类,我们先回忆一下,当子类继承父类时会发生什么?子类在继承父类时,会继承父类的所有成员,并且子类的构造函数(在初始化时)会合成父类的构造函数进行合成。蹬蹬蹬……那么,如果我们把父类的构造函数声明为私有(private)的,当子类在初始化调用构造函数时就会失败。但是,把构造函数声明为私有的,也就不能在类外创建对象了。所以,我们还需要在类中写一个静态的函数,返回该类。
下面是代码实现:
class Person
{
private:
Person(string name,int age)
:_name(name)
,_age(age)
{}
public:
static Person* GetPersonObj(string name,int age);
// static Person GetPersonObj(string name,int age); //方法2
void Display()
{
cout<<"名字:"<<_name<<",年龄:"<<_age<<endl;
}
private:
string _name;
int _age;
};
Person* Person::GetPersonObj(string name,int age)
{
Person* Instance = new Person(name,age);
return Instance;
}
//Person Person::GetPersonObj(string name,int age)
//{
// Person Instance(name,age);
// return Instance;
//}
这两种方法再创建类时和以往创建类时都有差别。
方法1创建类:
Person* p = Person::GetPersonObj("小红",12);
p->Display();
方法2创建类:
Person p = Person::GetPersonObj("小黑",14);
p.Display();
这种方法,当我们再写一个子类来继承这个Person类时,就会直接编译不通过。
2.如何实现一个只能在栈上生成对象的类
方法1:其实就是上面的方法2,基类的构造函数私有,然后写一个静态函数获取该类。
class Person
{
private:
Person(string name,int age)
:_name(name)
,_age(age)
{}
public:
static Person GetPersonObj(string name,int age)
{
Person Instance(name,age);
return Instance;
}
void Display()
{
cout<<"名字:"<<_name<<",年龄:"<<_age<<endl;
}
private:
string _name;
int _age;
};
方法2:重载operator new为私有,这样就不会在堆上生成对象了。但是这样有缺陷,在类外即静态区依然可以生成对象。
class Person
{
private:
Person(string name,int age)
:_name(name)
,_age(age)
{}
private:
void* operator new(size_t size);
void operator delete(void* p);
private:
string _name;
int _age;
};
operator new——>动态内存开辟 + 构造函数
该方法就是防止动态内存开辟。
敲黑板:这种方法在大多数情况下时可以满足要求的,但是还是不严谨,存在缺陷的,所以不建议使用该方法。不过,可以拓展我们的思维,对一道题可以从多个方面思考。
3.如何实现一个只能在堆上生成对象的类
这个实现的方法其实就是在第一题的第一种方法的基础上再防止拷贝构造和防止赋值。
class Person
{
private:
Person(string name,int age)
:_name(name)
,_age(age)
{}
public:
static Person* GetPersonObj(string name,int age);
void Display()
{
cout<<"名字:"<<_name<<",年龄:"<<_age<<endl;
}
private:
Person(const Person& p); //防止拷贝构造在堆上的类。
Person& operator=(const Person& p);
private:
string _name;
int _age;
};
Person* Person::GetPersonObj(string name,int age)
{
Person* Instance = new Person(name,age);
return Instance;
}
如果在函数中不将拷贝构造和赋值运算符的重载声明为私有的,该类的其它对象就可以拷贝构造堆上的对象,而拷贝构造出来的就在栈上,这样就不符合题意。
防止类的拷贝构造其实有两种方法:
- 只声明不定义。(有缺陷,可以将定义实现在类外静态区)
- 声明为私有。——->在类外就不可以使用。
其实,这3个相近的题只要懂了第一题,第二题和第三题就很简单了。