假设我实现了自己的链接列表,其节点可以包含“Car”类型的元素。
在这个实现中,我有一个方法PrintList()
,它有一个循环并为每个节点调用toString
方法。
我班上的内容供参考:
template<class T>
class ArrayList {
private:
class Node {
private:
// Node accessors
T* element;
public:
// ctor's
//Accessors etc
void GetElement();
string toString();
};
//members
int size;
// etc
public:
void PrintList();
};
节点toString()
看起来像这样:
string myNode::toString() {
// Returns a Car pointer.
// Still in myList implementation
// For a generic version I'ld want 'getEleemnt' or something.
return this->GetCar()->toString();
}
Car* Mylist::Node::GetCar() {
//Returns a car* ptr
return this->myCar;
//car has an implementation of toString() which is soon invoked.
}
//Inside my Car class written in some other cpp file, has no relationship
//with MyList.
string Car()::toString() {
//Car type is a set of enums defined in a header.
//Car has a EnumeratedType member field.
switch ( this->getEnumeratedType ) {
case 0:
return "I'm a veyron"
// etc
}
}
假设我现在实现自己的链接列表模板。 (因为作为一名学生,我发现练习很有趣并且是练习我的C ++的好机会)。以上toPrint()shenanigans不起作用。
template <class T>
string MyList<T>::myNode::toString() {
// Returns a T* pointer.
// now in generic <T> myList implementation
//
return this->GetElement()->toString(); // this does not compile....
}
template <class T>
T* Mylist<T>::Node::GetElement() {
//Returns a element* ptr?
return this->myElement;
// This compiles iirc.
}
似乎没有办法在未知的类模板上调用方法。 Car与myList没有任何关系,我可能有兴趣存储与Car无关的任何对象,假设我想存储花,即使它们都有toString实现,编译器也不允许我调用它们。
一个可能的建议是创建一个IPrintable接口,任何对象我都打算继承通用列表,但我不知道这是否真的解决了我的问题。
总结一下,我正在返回一个指针,输入“T”,可能是Car,或者可能是Flowers,我想知道是否有某种方式盲目地投掷toString()
飞镖并让它们调用他们的实施。
答案 0 :(得分:0)
好像你已经实现了自己的列表类,所以我不能对此发表评论。但是让我通过使用常规的stl容器来解释它。如果您有特定类型的容器:
std::vector<Car> cars;
你可以只输入那种类型: cars.push_back(车载()); cars.push_back(用户()); //错误
如果使用多态,则可以在使用指针时在容器内存储不同类型的对象(从同一基类继承):
#include <iostream>
#include <vector>
#include <memory>
class Car {
public:
virtual ~Car() {}
virtual std::string toString() const {
return "I'm a car";
}
};
class RaceCar : public Car {
public:
virtual std::string toString() const {
return "I'm a race car";
}
void raceCarSpecificMethod() const { }
};
int main() {
typedef std::shared_ptr<Car> CarPtr;
std::vector<CarPtr> cars;
cars.emplace_back(std::make_shared<Car>());
cars.emplace_back(std::make_shared<RaceCar>());
for (const auto &car : cars) {
std::cout << car->toString() << std::endl;
}
return 0;
}
但是,你不能以这种方式调用像“raceCarSpecificMethod()”这样的方法。如果要调用该方法,则必须将for循环更改为:
for (auto &car : cars) {
std::cout << car->toString() << std::endl;
std::shared_ptr<RaceCar> race_car = std::dynamic_pointer_cast<RaceCar>(car);
if (race_car) {
race_car->raceCarSpecificMethod();
}
}
dynamic_pointer_cast 将Car指针强制转换为RaceCar指针,使您可以使用raceCarSpecificMethod。您必须检查返回的指针是否为nullptr。如果转换指针不是RaceCar指针,则返回nullptr。如果上面的例子我使用了shared_ptrs,那么在使用常规指针时你应该使用:
RaceCar *race_car = dynamic_cast<RaceCar*>(car); // assuming that car is a Car*
我不确定你为什么要编写自己的列表类,但总的来说我建议你坚持使用std :: vector。