【C++】构造函数protected的说明
总结:
protected的构造函数,和private的构造函数,类似, 都是防止外部直接实例化对象,只能通过static方法才能new出对象,其实也不一定是new,主要是栈上创建被限制了,详见下面的例子说明
区别在于protected,可以被继承,只能进行派生类,而private的,不能派生,所有事情都必须在当前class内部实现
通常protected这种情况,class内部没有static方法,其目的就是为了让类只能被继承,不能实例化当前类,只能实例化子类。 构造,拷贝构造,复制运算符都是protected。 但是析构函数要声明成 protected,因为如果析构函数为private,派生类就不能调用。
注意,对于private构造函数,这里有一个破局的方式,如果在class类内部的一个方法,eg get_instance()方法中,返回一个临时的对象,此时是可以在栈上创建成功,也可以进行析构,但是返回栈上的临时实例的引用或指针,本身就是有问题的。如果返回的是实例,而不是指针,就要调用拷贝构造函数,这个拷贝构造函数也是在外部调用的,如果拷贝构造函数是private的,则编译不通过。
通常,是把这个方法声明为static,里面的局部变量也声明为static,这种其实就是一种单例模式,只是这种单例,对象是在static内存区,不是在堆上面
public A& A::get_instance()
{
A a; //此时可以创建成功,因为是A内部的function,可以调用A的构造函数,即使是private
return a; // 这里return,a会进行析构,也是类内部调用,可以编译通过。但是返回的是一个栈上的实例,调用结束后,内存已经释放,不符合编程规范。
}
private, 这种情况,通常就是单例模式,不能被继承,也不能在栈上实例化,只能在static方法中new出对象。
而,对应的,构造函数,拷贝构造函数,复制运算符都是private的,防止其他方式产生对象
析构函数,则
protected类型的,还有一个情况需要说明,参见链接 https://bbs.csdn.net/topics/392913065
// C++构造函数是protect的,子类的普通函数无法访问,但是子类的构造函数可以访问
class Base
{
protected: // protected
Base()
{
}
Base(const Base& base)
{
}
const Base& operator = (const Base&)
{
}
static void SFun()
{
}
void Fun()
{
}
};
class Son : public Base
{
public:
void Fun()
{
Base *p = new Base(); // error C2248: 'Base::Base': cannot access protected member declared in class 'Base'
Fun(); // OK
SFun(); // OK
}
Son()
{
}
Son(const Son & son)
{
}
};
其实本质:
本质是new 了一个新的base的实例,这个实例和当前Son的实例不是同一个,也就是son只能访问自己内部的base类的protected方法
new出来的是另外一个base实例,跟当前实例没有关系,是两个相互独立的实例,因此son实例不能访问另外一个实例的protected方法
原因解释:
https://en.cppreference.com/w/cpp/language/access
protected的构造函数只能在派生类构造函数的初始化列表上进行访问,以对对象本身进行初始化。
其它protected成员函数在派生类中也只能基于派生类去访问。
Protected member access
Protected members form the interface for the derived classes (which is distinct from the public interface of the class).
A protected member of a class Base can only be accessed
1) by the members and friends of Base
2) by the members and friends (until C++17) of any class derived from Base, but only when operating on an object of a type that is derived from Base (including this)
1. 被Base的成员和友元访问。
2. 被任何派生类对象的成员和友元访问,并且这个仅仅是在操作这个派生类对象时。显然可以看出,只能通过派生类对象调用操作派生类对象,而不能在派生类里独立地去调用基类的构造方法去创建Base对象。
https://bbs.csdn.net/topics/392913065
========================= 百度知道上面很好的一个回答
https://www.cnblogs.com/this-543273659/archive/2011/08/02/2125487.html