2013-10-09 3 views
0

У меня возникают проблемы с получением вектора объектов для печати имени производного класса, а не базового класса.Использование функции базового класса с значениями производного класса

Это мои классы

#include <vector> 
#include <iostream> 

using namespace std; 

class Object 
{ 
    string name; 
public: 
    string getName() 
    { 
     return name; 
    } 
}; 

class Flashlight : public Object 
{ 
    string name = "Flashlight"; 
public: 
    string getName(); 
}; 

Это мое главное, он имеет вектор объектов и в этот момент просто нужно распечатать их имена.

int main() 
{ 
    vector<Object> items; 
    items.push_back(*new Flashlight); 

    for(int i = 0; i < items.size(); i++) 
    { 
     cout << i+1 << " " << items.at(i).getName(); 
    } 
} 

Прямо сейчас, если я назначу то имя в объекте будет печатать это, но его не используют производные классы значения, я просто хочу, чтобы наследовать функцию затем использовать его собственные значения с ним. Я пробовал реализовать функцию в базовых классах (но, видя, что у меня может быть много таких в будущем, это приведет к большому количеству избыточного кода), но это тоже не сработает.

+0

Вам нужен вектор указателей – ST3

+1

Ваш код страдает от нарезки объектов. Поскольку у вас есть вектор «», любой «фонарик» * нарезается * на объект, когда вы добавляете его в свой вектор. Вам нужен 'vector '. Есть и другие проблемы с вашим кодом, но я думаю, что они просто пытаются исправить то, что является фундаментальной ошибкой нарезки объектов. – john

+0

@john: попытка переопределить переменную элемента также является серьезной проблемой. Оба должны быть решены. –

ответ

1

Попробуйте так:

int main() 
{ 
    vector<Object *> items; 
    items.push_back(new Flashlight); 

    for(int i = 0; i < items.size(); i++) 
    { 
     cout << i+1 << " " << items.at(i)->getName(); 
    } 
} 

Кроме того, как упоминалось в другой ответ, было бы хорошо использовать virtual методы чтения об этом here.

Что еще вам нужно использовать конструктор, чтобы установить значение для переменной name. Вы можете прочитать о них here

Вы должны попробовать этот способ:

class Object 
{ 
private: 
    string name; 
public: 
    Object() : name("Object") 
    {} 
    Object(string str) : name(str) 
    {} 

    string getName() 
    { 
     return name; 
    } 
}; 

class Flashlight : public Object 
{ 
public: 
    Flashlight() : Object("Flashlight") 
    {} 

    string getName(); 
}; 
+0

Это только часть проблемы. Переменная все еще не инициализирована должным образом. –

+0

Да, это сработало, я пытался использовать указатели раньше, но использовал их неправильно, спасибо за вашу помощь! – breezy

+0

@ user2861504 Если бы это было действительно полезно, вы должны принять ответ. Вот как работает система SO –

3

Вместо того, чтобы объявить переменную «имя» в производных классах, инициализировать значения переменных в качестве пользовательского значения для этого производного класса. Также я бы предложил вам сделать метод getName виртуальным. Вам также не нужно переопределять метод getName в производных классах, если вы просто хотите вывести имя.

+0

Это только часть проблемы. Коллекция имеет объект, а не фонарики. –

+0

Что делать, если вы не переопределяете переменную имени в производном классе и не инициализируете значение имени (определенное в базе) в производном классе с использованием конструктора/сеттера или чего-то еще. –

+0

Это то, что вы должны делать, да. –

1

Ваш код имеет две проблемы:

  1. getName() не является виртуальным. Это означает, что указанная фактическая функция определяется во время компиляции на основе переменной статического типа. Таким образом, если переменная имеет тип Object, Object& или Object* (или любой const вариации на тех), функция Object::getName() будет называться, независимо от фактического типа объекта называется или на который указывает переменной (динамический типа).
  2. У вас есть vector<Object>, что означает, что все хранящиеся в нем объекты имеют тип Object. Вы можете попытаться поместить в него объект Flashlight, но только часть Object будет скопирована в вектор. Если вам нужен полиморфизм в vector<>, вам нужен вектор указателей (или даже лучше, умных указателей).

Таким образом, вы должны сделать две вещи, чтобы получить желаемое поведение:

  1. функцию Declare getName() в virtual string getName() (даже лучше, virtual const string& getName() const)
  2. Объявить items в vector<Object*> items (еще лучше, использовать соответствующий умный указатель, такой как unique_ptr<> вместо необработанного указателя )
Смежные вопросы