我尝试使用抽象/接口类Base
的向量作为函数g
(在main.cpp
中)的参数,以便我可以将派生类的向量作为参数传递。
因为我不能有Base
的示例,所以我尝试传递唯一指针的向量--因为这似乎是首选的方式。但是,由于某种原因,我不允许从vector<unique_ptr<Test::A>>
转换为vector<unique_ptr<Test::Base>>
,我不明白为什么。
问题:为什么不允许这样做?我该如何解决?
module.hpp
看起来像这样:
#ifndef _MODULE_HPP
#define _MODULE_HPP
namespace Test
{
class Base
{
public:
virtual ~Base(){};
virtual int f(int a, int b) = 0;
};
class A : public Base
{
public:
A();
~A() = default;
int f(int a, int b);
};
}
#endif
module.cpp
看起来像这样:
#include <module/module.hpp>
Test::A::A() {}
int Test::A::f(int a, int b)
{
return a + b;
};
main.cpp
看起来像这样:
#include <module/module.hpp>
#include <iostream>
#include <vector>
#include <memory>
void g(std::vector<std::unique_ptr<Test::Base>> v)
{
for (std::unique_ptr<Test::Base> &vi : v)
{
std::cout << vi->f(1, 2) << " ";
}
std::cout << std::endl;
}
int main(int argc, char **argv)
{
(void)argc;
(void)argv;
std::vector<std::unique_ptr<Test::A>> v;
v.emplace_back(std::make_unique<Test::A>());
v.emplace_back(std::make_unique<Test::A>());
g(v);
return 0;
}
当我尝试编译代码时,我得到以下错误:
g++ -std=c++17 -Wall -Wextra -I src -I include -c -o build/module/module.o src/module/module.cpp
g++ -std=c++17 -Wall -Wextra -I src -I include -c -o build/main.o src/main.cpp
src/main.cpp: In function ‘int main(int, char**)’:
src/main.cpp:26:4: error: could not convert ‘v’ from ‘vector<unique_ptr<Test::A>>’ to ‘vector<unique_ptr<Test::Base>>’
26 | g(v);
| ^
| |
| vector<unique_ptr<Test::A>>
make: *** [Makefile:36: build/main.o] Error 1
1条答案
按热度按时间pwuypxnk1#
std::vector<std::unique_ptr<Base>>
和std::vector<std::unique_ptr<Derived>>
不是covariant,它们之间不存在转换函数,因此不能简单地将一个视为另一个。它们是完全不同的,不相关的类型。多态存储
如果你需要多态存储,为什么不到处都使用
std::vector<std::unique_ptr<Base>>
呢?你可以像这样插入std::unique_ptr<Derived>
:接受协变类型向量
或者,如果你只需要存储一个
std::vector<Derived>
,但想将它传递到接受一系列Base
值的函数中,你可以这样做:要调用
g
,我们需要在main
中声明std::vector<Test::A> v;
。如果我们使用范围,我们可以使这个函数更加通用,所以我们不再特别依赖std::vector
。