我有 Java (OOP) 背景。我做了一个简单的类来说明我的问题:
#include <list>
#include <string>
#include <iostream>
// classes
class InterfaceA
{
public:
virtual std::string functionA();
};
class InterfaceB
{
public:
virtual std::string functionB();
};
class DerivedAB : public InterfaceA, public InterfaceB
{
public:
std::string functionA()
{
return "I'm a A object";
}
std::string functionB()
{
return "I'm a B object";
}
};
// functions
void doStuffOnListOfA(std::list<InterfaceA*> aElements)
{
std::cout << "Print list of A" << std::endl;
for (InterfaceA* const& a : aElements)
{
std::cout << a->functionA() << std::endl;
}
};
int main()
{
std::list<DerivedAB*> derivedABs;
doStuffOnListOfA(derivedABs);
return 0;
}
我有两个简单的虚拟类 InterfaceA
和InterfaceB
和一个类DerivedAB
该多重继承了前两个虚拟类。
此外,我还创建了一个 DerivedAB
的指针列表。 ( std::list<DerivedAB *>
) 并希望将此列表与设计用于处理 InterfaceA
列表的函数一起使用。 -派生对象。但我收到一个错误:
(base) ❮ onyr ★ kenzae❯ ❮ multi_inheritance_type_convertion❯❯ make
g++ -c -o main.o main.cpp
main.cpp: In function ‘int main()’:
main.cpp:54:32: error: could not convert ‘derivedABs’ from ‘std::__cxx11::list<DerivedAB*>’ to ‘std::__cxx11::list<InterfaceA*>’
doStuffOnListOfA(derivedABs);
我显然有一个类型转换错误。我在 Stack Overflow 上读过很多关于 C++ 中的不同类型转换以及多重继承的文章,但我的大脑拒绝给我答案。
编辑:
我说了一个错误的说法:
"However I'm pretty sure such a code would work in Java..."
显然我缺少一个关于类型继承的重要概念......
最佳答案
C++ 与 Java 有很大不同!
I have obviously a type casting error.
你是对的(又名:类型不匹配)! std::list
是一个标准模板容器,当您使用模板参数实例化时,它为您提供具体类型。
这意味着 std::list<InterfaceA*>
与 std::list<DerivedAB *>
不同.
这正是编译器告诉您的:
error: could not convert
from ‘std::__cxx11::list<DerivedAB*>’ ----> i.e. std::list<DerivedAB*>
to ‘std::__cxx11::list<InterfaceA*>’ ----> i.e std::list<InterfaceA*>
doStuffOnListOfA(derivedABs); ----> at the function call
您不能隐式(即编译器不会)相互转换。
您需要强制转换 derivedABs
的每个元素到基指针或(在你的情况下)使 doStuffOnListOfA
作为模板函数:
template<typename T>
void doStuffOnListOfA(std::list<T*> aElements)
{
std::cout << "Print list of A" << std::endl;
for (InterfaceA* a : aElements)
{
std::cout << a->functionA() << std::endl;
}
};
为了确保这一点,仅将上述内容用于 std::list<derived from InterfaceA and B>
,您可以(可选)SFINAE模板函数:
#include <type_traits> // std::is_base_of
template<typename T>
constexpr bool isBaseOfInterfaces = std::is_base_of_v<InterfaceA, T> && std::is_base_of_v<InterfaceB, T>;
template<typename T>
auto doStuffOnListOfA(std::list<T*> aElements)
-> std::enable_if_t<isBaseOfInterfaces<T>, void>
{
// ... code
};
话虽如此,
- 您需要查看智能指针(例如
std::unique_ptr
、std::shared_ptr
),而不是使用原始指针(手动内存管理),这样您就可以智能地处理内存管理。 - 您可能需要添加
virtual
基类中的析构函数用于定义的行为。请参阅此处了解更多信息:When to use virtual destructors?
这里是( the complete demo )
关于c++ - 与 std::list 一起使用的指针上的接口(interface)类型转换的多重继承,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68806059/