在c++中(不仅限于c++),一个函数被声明为protected或者private时,那也就意味着不能被外部直接调用了:
//类的成员函数add()是private
class cla{
private:
int add(int a, int b){
return a + b;
}
public:
int my_func(){
add(5, 6); //private属性的函数只能在类内部使用
}
};
int main(void)
{
cla c;
//c.add(4, 2); //private属性的函数不能在类外部使用,error
c.my_func(); //正确
return 0;
}
//类的成员函数add()是protected
class cla{
protected:
int add(int a, int b){
return a + b;
}
public:
int my_func(){
add(5, 6); //private属性的函数只能在类内部使用
}
};
class subCla : public cla
{
public:
int sun_func(){
add(6, 6); //subCla继承于cla,所以它可以访问父类cla的protected属性的add函数,ok
return 0;
}
};
int main(void)
{
cla c;
subCla s;
s.sun_func(); //ok
c.add(7, 6); //error
return 0;
}
总归,对于protected函数,只能造子类内部和本类内部调用,private函数,只能在本类内部中调用。这些都是c++最基础的知识,这里只是顺带提一下。
那么将构造函数/析构函数声明为protected或者private?可以通过以下使用场景来看:
1) 作为类设计者的你,不希望你定义的类(cla)可以生成对象,而是要让调用者定子类subCla来继承cla后,子类可以生成对象。那么就要将cla的构造/析构函数声明为protected,子类subCla的构造/析构函数为public:
class cla{
protected:
cla(){}
~cla(){}
public:
void my_func(){}
};
class subCla : public cla{
public:
void func(){
}
};
int main(void)
{
cla c; //error,cla的构造函数是protected,生成对象时该类构造函数要被外界自动得到调用,二者相悖
subCla s; //ok,cla的构造函数是protected,可以在子类内部调用,生成对象时该类构造函数要被子类自动得到调用
return 0;
}
2) 设计类时,如果将类的构造/析构函数声明为private,那么也就说明只能在类的内部去生成本类的对象了:
class cla{
private:
cla(){}
~cla(){}
public:
void interface(){
cla c;
}
};
如上的类是符合语法要求的,但是由于该类不能在外部生成对象,所以interface()这个方法将不能被调用。除非将interface()声明为static:
class cla{
private:
cla(){}
~cla(){}
public:
static void interface(){
cla c;
}
};
int main(void)
{
cla::interface();
return 0;
}
这样做的意义貌似也不大,我们需要的是像定义一个对象去调用该类成员方法和成员变量的效果,这样子仿佛就只能使用类中的inteaface()这个函数。其他成员无法操作到。既然如此,我们可以把类内部生成的对象的地址给获取回来,这样不就可以通过地址访问其他成员了。但是特别注意,返回的地址一定不能是在栈上面的,因为一旦interface()函数退出,该堆栈信息就会消失,所以interface()函数内部的生成对象放在静态区:
class cla{
private:
cla(){}
~cla(){}
public:
static cla* interface(){
static cla c;
return &c;
}
void my_func(){
std::cout<<"hello"<<std::endl;
}
};
int main(void)
{
cla *p_cla = NULL;
p_cla = cla::interface();
p_cla->my_func();
return 0;
}
其实这已经是设计模式中的单例模式了,
p_cla = cla::interface();
p_cla->my_func();
这两句代码无论调用几次,不论在哪一个文件、函数调用,得到的都是静态区中同一个cla类的对象的地址。