我正在尝试使用具有相同基类的不同子类指针的向量。该向量设置为基类指针,但是添加到该向量的任何内容都无法获得其子类的全部功能。 在错误日志中可以看到它被视为基类,因此无法获得扩展功能。
我查看了很多问题,人们说要按照我的方式去做,但是出于某种原因,它是行不通的。
该代码位于公共仓库中。
https://repl.it/@cubingminer8/inheritance-with-vectors-testing
任何帮助将不胜感激!
edit:好的,所以我将在c ++ sdl2游戏引擎中将其用于sprite组系统。将有一个基本的Sprite类,其中包含一些基本的东西,例如render和move,而我需要的任何Sprite都是它们自己的继承自Sprite的类,它们将具有自己的独特行为,因此虚函数是不切实际的。将有一个sprite组对象,可以存储从Sprite继承的对象。这样就可以一次全部渲染它们。
如果您曾经使用过 pygame ,那么它与那里使用的sprite和spritegroup系统几乎相同。 https://www.pygame.org/docs/tut/SpriteIntro.html
#include <iostream>
#include <vector>
class Base {
public:
char A = 'A';
};
class Sub : public Base {
public:
char B = 'B';
};
class Sub2 : public Base {
public:
char C = 'C';
};
int main() {
std::vector<Base*> List;
List.push_back(new Sub());
List.push_back(new Sub2());
std::cout << List[0]->B << std::endl; // it should be able to print B
std::cout << List[1]->C << std::endl; // but it is being set as a base class and
// not getting the functionality of the subclass it is.
}
答案 0 :(得分:4)
通常,这是通过虚拟功能实现的。在给定的情况下,它应该是一个虚拟的getter函数,该函数返回每个类的char
个成员。
class Base {
char A = 'A';
public:
virtual char getChar()const /*noexcept*/ { return A; }
virtual Base () = default;
};
class Sub : public Base {
char B = 'B';
public:
char getChar()const /*noexcept*/ override { return B; }
};
class Sub2 : public Base {
char C = 'C';
public:
char getChar()const /*noexcept*/ override { return C; }
};
现在在主要
std::cout << List[0]->getChar() << std::endl;
作为旁注,建议您查看smart pointers而不是行指针,从而避免手动存储管理。
一个好的开始是:
#include <memory>
std::vector<std::unique_ptr<Base>> List;
List.emplace_back(std::make_unique<Sub>());
答案 1 :(得分:2)
因此,您希望它能够正常工作:
// your code version 1
std::cout<< List[0]->B << std::endl; //it should be able to print B
std::cout<< List[1]->C << std::endl; //but it is being set as a base class
但是如果您改写此代码,应该怎么办?
// your code version 2
std::cout<< List[0]->C << std::endl;
std::cout<< List[1]->B << std::endl;
List[0]
没有任何C
,而List[1]
没有任何B
。您打算如何处理此代码?
有几种方法可以解决这个问题。
reinterpret_cast
之类的方法来绕过C ++的类型系统,但这非常危险,因此不建议使用。正如其他人提到的那样,扩展类功能的(唯一)正确方法是通过虚函数。这需要进行一些计划。尽管不需要知道 派生类将如何实现它们,但基数至少应声明需要进行哪些操作。