C++ 复制构造函数被隐式删除,因为默认定义的格式不正确

C++ 复制构造函数被隐式删除,因为默认定义的格式不正确,c++,clone,copy-constructor,private-constructor,C++,Clone,Copy Constructor,Private Constructor,我有一个类a(来自一个我无法控制的库),带有一个私有副本构造函数和一个clone方法,还有一个从a派生的类B。我还想为B实现clone 天真的方法 #包括 A类{//我在这里没有控制权 公众: A(int A){}; std::共享的ptr 克隆()常量 { 返回std::shared_ptr(新的A(*this)); } 私人: A(常数A&A){}; }; B类:公共A{ 公众: B(内部数据,内部外部数据): A(数据), 外部数据(外部数据) { } std::共享的ptr 克隆()常量

我有一个类
a
(来自一个我无法控制的库),带有一个私有副本构造函数和一个
clone
方法,还有一个从
a
派生的类
B
。我还想为
B
实现
clone

天真的方法

#包括
A类{//我在这里没有控制权
公众:
A(int A){};
std::共享的ptr
克隆()常量
{
返回std::shared_ptr(新的A(*this));
}
私人:
A(常数A&A){};
};
B类:公共A{
公众:
B(内部数据,内部外部数据):
A(数据),
外部数据(外部数据)
{
}
std::共享的ptr
克隆()常量
{
返回std::shared_ptr(新B(*this));
}
私人:
int-extraData;
};
int main(){
A(1);
}
但是,失败,因为
A
的复制构造函数是私有的:

main.cpp: In member function ‘std::shared_ptr<B> B::clone() const’:
main.cpp:27:42: error: use of deleted function ‘B::B(const B&)’
     return std::shared_ptr<B>(new B(*this));
                                      ^
main.cpp:17:7: note: ‘B::B(const B&)’ is implicitly deleted because the default definition would be ill-formed:
 class B: public A {
       ^
main.cpp:14:5: error: ‘A::A(const A&)’ is private
     A(const A & a) {};
     ^
main.cpp:17:7: error: within this context
 class B: public A {
main.cpp:在成员函数“std::shared_ptr B::clone()const”中:
main.cpp:27:42:错误:使用已删除的函数“B::B(常量B&)”
返回std::shared_ptr(新B(*this));
^
main.cpp:17:7:注意:“B::B(const B&)”被隐式删除,因为默认定义的格式不正确:
B类:公共A{
^
main.cpp:14:5:错误:“A::A(const A&)”是私有的
A(常数A&A){};
^
main.cpp:17:7:错误:在此上下文中
B类:公共A{

对于
B::clone()
,可能有一种方法可以使用
a::clone()
,但我不确定这到底是如何工作的。有什么提示吗?

您需要保护
a
的复制构造函数,以便派生类可以使用它:

protected:
    A(const A & a) { /*...*/ }

希望能有所帮助。

之所以
B
的复制构造函数的默认定义格式不正确,是因为如果允许的话,它将调用
B
的私有(因此无法访问)和未定义的
A
的复制构造函数


A
的复制构造函数设置为受保护的或公共的,以便
B
可以访问它。另一个(非常糟糕)选项是将类
B
声明为
a
的朋友。所有可能的情况都要求您为
a
的副本构造函数提供定义。

我认为这是一个打字错误,您的
B
根本没有公共成员, 在定义
B::B(int,int)
之前,您缺少了一个
public:

您的
A
所代表的类的作者显然希望它是 可克隆但不可复制。这表明他或她想要所有 实例在堆上生存。但相反,还有公众 构造函数
A::A(int)
。你确定这是对的吗

假设这个类可以揭示足够的信息是有道理的 关于一个给定的实例来构成另一个实例 在
a
上多一点肉:

class A {
public:
    A(int a) 
    : data_(a){};

    std::shared_ptr<A>
    clone() const
    {
        return std::shared_ptr<A>(new A(*this));
    }

    int data() const {
        return data_;
    }

private:
    A(const A & a) {};
    int data_;
};
所以我不太相信
A
能忠实地代表问题 然而,从表面上看,你需要回答的问题 is:你能不方便地复制一个
A

如果没有,那么你就卡住了。如果是这样,那么你可以使用不方便的副本 构造
A
以明确定义
B
的常规复制构造函数, 这就是你所需要的

class B: public A {
public:
    B(B const & other)
    : A(other.data()),extraData_(other.extraData_){}    

    B(int data, int extraData):
    A(data),
    extraData_(extraData)
    {
    }

    std::shared_ptr<B>
    clone() const
    {
        return std::shared_ptr<B>(new B(*this));
    }

    int extradata() const {
        return extraData_;
    }

private:
    int extraData_;
};

#include <iostream>

int main()
{
    B b(1,2);
    std::shared_ptr<B> pb = b.clone();
    std::cout << pb->data() << std::endl;
    std::cout << pb->extradata() << std::endl;
    return 0;
} 
B类:公共A类{
公众:
B(建筑及其他)
:A(other.data()),extraData(other.extraData){
B(内部数据,内部外部数据):
A(数据),
外部数据(外部数据)
{
}
std::共享的ptr
克隆()常量
{
返回std::shared_ptr(新B(*this));
}
int extradata()常量{
返回外部数据;
}
私人:
int-extraData;
};
#包括
int main()
{
B(1,2);
std::shared_ptr pb=b.clone();

std::cout data()我无法控制
A
,因为它来自一个库;我在原始帖子中对此进行了澄清。那么你不应该从
A
@NicoSchlömer:Ohh.在这种情况下,从
A
派生是个坏主意。你现在应该使用组合,而不是继承。从
A
派生是个坏主意所有的。拥有一个私有的(省略的)拷贝构造函数是一个很大的提示,开发者不鼓励做各种事情,包括使用
a
作为基类。这是一个普遍的规则:“不要从具有私有拷贝构造函数的类派生”?我现在不太明白为什么。我无法控制一个来自图书馆的文件,因为它来自图书馆;我在原始帖子中对此进行了澄清。根据我对该澄清做出的评论(纳瓦兹的帖子下方)拥有一个私有构造函数是一个非常重要的提示,您不应该从
a
派生。是否也没有办法使用
a::clone()
class B: public A {
public:
    B(B const & other)
    : A(other.data()),extraData_(other.extraData_){}    

    B(int data, int extraData):
    A(data),
    extraData_(extraData)
    {
    }

    std::shared_ptr<B>
    clone() const
    {
        return std::shared_ptr<B>(new B(*this));
    }

    int extradata() const {
        return extraData_;
    }

private:
    int extraData_;
};

#include <iostream>

int main()
{
    B b(1,2);
    std::shared_ptr<B> pb = b.clone();
    std::cout << pb->data() << std::endl;
    std::cout << pb->extradata() << std::endl;
    return 0;
}