【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类型的,还有⼀个情况需要说明,参见链接
// 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⽅法
原因解释:
en.cppreference/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对象。
=========================  百度知道上⾯很好的⼀个回答
将构造函数,析构函数声明为私有和保护的,那么对象如何创建?
已经不能从外部调⽤构造函数了,但是对象必须被构造,应该如何解决,⿇烦⼤家帮忙说明,关于构造,析构函数声明为私有和保护时的⽤法
提出这个问题,说明你已经对c++有所思考了。
从语法上来讲,⼀个函数被声明为protected或者private,那么这个函数就不能从“外部”直接被调⽤了。
对于protected的函数,⼦类的“内部”的其他函数可以调⽤之。
⽽对于private的函数,只能被本类“内部”的其他函数说调⽤。
语法上就是这么规定的,你肯定也知道的咯。
那么为什么有时候将构造函数或者析构函数声明为protected的或者private的?
通常使⽤的场景如下:
1。如果你不想让外⾯的⽤户直接构造⼀个类(假设这个类的名字为A)的对象,⽽希望⽤户只能构造这个类A的⼦类,那你就可以将类A的构造函数/析构函数声明为protected,⽽将类A的⼦类的构造函数/析
构函数声明为public。例如:class A
{ protected: A(){}
public: ....
};
calss B : public A
{ public: B(){}
....
};
A a; // error
B b; // ok
2. 如果将构造函数/析构函数声明为private,那只能这个类的“内部”的函数才能构造这个类的对象了。这⾥所说的“内部”不知道你是否能明⽩,下⾯举个例⼦吧。
class A
{
private:
A(){  }
~A(){ }
public:
void Instance()//类A的内部的⼀个函数
{
A a;
}
};
上⾯的代码是能通过编译的。上⾯代码⾥的Instance函数就是类A的内部的⼀个函数。Instance函数体⾥就构建了⼀个A的对象。
但是,这个Instance函数还是不能够被外⾯调⽤的。为什么呢?
如果要调⽤Instance函数,必须有⼀个对象被构造出来。但是构造函数被声明为private的了。外部不能直接构造⼀个对象出来。
A aObj; // 编译通不过
aObj.Instance();
但是,如果Instance是⼀个static静态函数的话,就可以不需要通过⼀个对象,⽽可以直接被调⽤。如下:class A
{
private:
A():data(10){ cout << "A" << endl; }
~
A(){ cout << "~A" << endl; }
public:
static A& Instance()
{
static A a;
return a;
}
void Print()
{
cout << data << endl;
}
private:
int data;
};
A& ra = A::Instance();
ra.Print();
上⾯的代码其实是设计模式singleton模式的⼀个简单的C++代码实现。
还有⼀个情况是:通常将拷贝构造函数和operator=(赋值操作符重载)声明成private,但是没有实现体。
这个的⽬的是禁⽌⼀个类的外部⽤户对这个类的对象进⾏复制动作。
细节请看《effective C++》⾥⾯的⼀个条款。具体哪个条款不记得了。