使用模板访问对象数据/方法成员

时间:2013-11-18 01:10:37

标签: c++ list templates

假设我实现了自己的链接列表,其节点可以包含“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()飞镖并让它们调用他们的实施。

1 个答案:

答案 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。