我试图通过使用来理解“类型擦除”的行为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)
这个错误的根本原因是什么?是关于类和结构之间的区别吗?是因为类是引用而结构是值吗?
classC++ 中 a和 a之间的唯一真正区别struct是,对于 a struct,默认成员访问和继承是public,而对于 a class,默认成员访问和继承是private。
因此,要使您的代码适用于class Derived模板,只需将其继承设置为Basepublic:
template< typename T >\nclass Derived : public Base { // public inheritance\npublic:\n//...\nRun Code Online (Sandbox Code Playgroud)\n这种public继承使Derived类可以访问Base类构造函数。
或者,要使您的struct模板案例失败 \xe2\x80\x93 最有可能出现完全相同的错误消息 \xe2\x80\x93 您可以使其继承Base private:
template< typename T >\nstruct Derived : private Base { // private inheritance - fails to compile!\npublic:\n//...\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
101 次 |
| 最近记录: |