在 C++ 中使用 std::make_shared 的“类型擦除”代码中的类和结构有什么区别?

Sad*_*Kao 1 c++

我试图通过使用来理解“类型擦除”的行为std::make_shared。基本思想是使用一个类Object来包装一些不同的类,例如类Foo和类Bar。

我编写了以下代码,它确实有效。

// TypeErasure.cpp

#include <iostream>
#include <memory>
#include <string>
#include <vector>

class Base
{
public:
    virtual ~Base() {}
    virtual std::string getName() const = 0;
};

template< typename T >
struct Derived : Base
{
public:
    explicit Derived(const T&& t) : objD(t) {}
    std::string getName() const override
    {
        return objD.getName();
    }
private:
    T objD;
};

class Object
{

public:
    template <typename T>
    explicit Object(T&& t)
        : objPtr(std::make_shared<Derived<T>>(std::forward<T>(t))) {}

    std::string getName() const
    {
        return objPtr->getName();
    }

    std::shared_ptr<const Base> objPtr;
};


void printName(std::vector<Object> vec)
{
    for (auto v: vec) std::cout << v.getName() << std::endl;
}

class Bar
{
public:
    std::string getName() const
    {
        return "Bar";
    }
};

class Foo
{
public:
    std::string getName() const
    {
        return "Foo";
    }
};

int main()
{
    std::vector<Object> vec{Object(Foo()), Object(Bar())};

    printName(vec);

}

Run Code Online (Sandbox Code Playgroud)

但是当我将“struct Derived:Base”更改为“class Derived:Base”时,它显示以下错误。

错误:没有匹配的函数可用于调用 'std::shared_ptr::shared_ptr(std::shared_ptr)'|

代码如下。

// TypeErasure.cpp

#include <iostream>
#include <memory>
#include <string>
#include <vector>

class Base
{
public:
    virtual ~Base() {}
    virtual std::string getName() const = 0;
};

template< typename T >
class Derived : Base
{
public:
    explicit Derived(const T&& t) : objD(t) {}
    std::string getName() const override
    {
        return objD.getName();
    }
private:
    T objD;
};

class Object
{

public:
    template <typename T>
    explicit Object(T&& t)
        : objPtr(std::make_shared<Derived<T>>(std::forward<T>(t))) {}

    std::string getName() const
    {
        return objPtr->getName();
    }

    std::shared_ptr<const Base> objPtr;
};


void printName(std::vector<Object> vec)
{
    for (auto v: vec) std::cout << v.getName() << std::endl;
}

class Bar
{
public:
    std::string getName() const
    {
        return "Bar";
    }
};

class Foo
{
public:
    std::string getName() const
    {
        return "Foo";
    }
};

int main()
{
    std::vector<Object> vec{Object(Foo()), Object(Bar())};

    printName(vec);

}
Run Code Online (Sandbox Code Playgroud)

这个错误的根本原因是什么?是关于类和结构之间的区别吗?是因为类是引用而结构是值吗?

Adr*_*ica 7

classC++ 中 a和 a之间的唯一真正区别struct是,对于 a struct,默认成员访问和继承public,而对于 a class,默认成员访问和继承是private

\n

因此,要使您的代码适用于class Derived模板,只需将其继承设置为Basepublic:

\n
template< typename T >\nclass Derived : public Base { // public inheritance\npublic:\n//...\n
Run Code Online (Sandbox Code Playgroud)\n

这种public继承使Derived类可以访问Base类构造函数。

\n
\n

或者,要使您的struct模板案例失败 \xe2\x80\x93 最有可能出现完全相同的错误消息 \xe2\x80\x93 您可以使其继承Base private

\n
template< typename T >\nstruct Derived : private Base { // private inheritance - fails to compile!\npublic:\n//...\n
Run Code Online (Sandbox Code Playgroud)\n