继承,复制构造函数和隐式类型转换

时间:2018-12-13 15:32:47

标签: c++ inheritance casting copy-constructor

我有一个派生类,我希望能够使用copy构造函数构造它的参数是基类的实例。

我确信这在C ++中应该可行。这是一个示例:

#include <string>


class Base
{

public:

    friend
    void swap(Base& l, Base& r)
    {
        using std::swap;

        swap(l.a, r.a);
    }

    Base()
        : a{1}
    {
    }

    Base(const int a)
        : a{a}
    {
    }

    virtual
    ~Base()
    {
    }

    Base(const Base& base)
        : a{base.a}
    {
    }

    Base(Base&& base)
        : Base()
    {
        swap(*this, base);
    }

    Base& operator=(Base base)
    {
        swap(*this, base);

        return *this;
    }

protected:

    int a;

};


class Derived : public Base
{


protected:

    std::string b;

};

int main()
{

    Base base(2);
    Derived derived(base);

}

错误(g++ main.cpp)是:

main.cpp: In function ‘int main()’:
main.cpp:71:31: error: no matching function for call to ‘Derived::Derived(Base&)’
     class Derived derived(base);
                               ^
main.cpp:57:7: note: candidate: Derived::Derived()
 class Derived : public Base
       ^~~~~~~
main.cpp:57:7: note:   candidate expects 0 arguments, 1 provided
main.cpp:57:7: note: candidate: Derived::Derived(const Derived&)
main.cpp:57:7: note:   no known conversion for argument 1 from ‘Base’ to ‘const Derived&’
main.cpp:57:7: note: candidate: Derived::Derived(Derived&&)
main.cpp:57:7: note:   no known conversion for argument 1 from ‘Base’ to ‘Derived&&’

因此,编译器不知道如何从Base实例隐式转换为Derived

我认为这在C ++中应该合法。我需要明确的转换声明吗?

5 个答案:

答案 0 :(得分:1)

您自己在做什么并没有多大意义,因为Base不是Derived的子类型,因此不能用作它的替换/替代,但是您可以尝试通过编写一个转换构造函数使其具有某种意义(与任何其他类型的初始化相同):

class Derived : public Base
{
public:
Derived(const Base &bs) : Base(bs), b("constructed from base") {}

protected:

    std::string b;

};

这将首先初始化Derived中的Base bs部分,然后使用一些值初始化字符串b(尽管您可以将其保留为空白)默认初始化为空字符串。

https://godbolt.org/z/GMELW_

答案 1 :(得分:0)

是的,您需要明确地从Base强制转换为Derived。每辆梅赛德斯都是汽车,但并不是每辆车都是梅赛德斯。

答案 2 :(得分:0)

有一个解决此问题的简单方法:通过将Base构造函数拉到Derived的范围内。

这可以通过using语句完成:

class Derived : public Base
{
public:
    using Base::Base;  // Pulls in the Base class constructors into the scope of Derived

    ...
};

答案 3 :(得分:0)

此语句Derived derived(base);或为简化B b(A());进行类型A到类型B的隐式转换,仅当class B直接继承或继承时才合法。间接来自Class A

为什么?因为class B可能包含新信息,所以在您的情况下,string b和强制类型转换不会“附加”信息。

答案 4 :(得分:0)

我找到了想要的东西(我不记得这个名字,所以之前也无法在Google上搜索它)。但是由于我正在使用继承,因此该技术实际上不起作用。 (或者至少我不知道如何使它工作。)

类型转换运算符:

Base::operator Derived()
{
    Derived derived;
    derived.a = a;
    return derived;
}

这实际上并不编译,因为编译器不知道Derived是什么。 (由于Derived继承自Base。)我不知道是否可以通过分离编译单元来完成这项工作。