2016-03-28 31 views
0

Setting a variable in a child class中,我試圖弄清楚如何正確地派生多態類中的變量。經過一些幫助後,我發現我需要在指針上使用dynamic_cast來正確訪問我需要的信息。我在這方面遇到了一些麻煩。正確執行動態轉換

這是我目前正在使用的功能。

void translateLines(Parser parser, Code code) 
{ 
    while(parser.hasMoreCommands()) 
    { 
     vector<Command>::const_iterator it = parser.currentCommand(); 
     if(it->commandType() == "A") 
     { 
      //SubType* item = dynamic_cast<SubType*>(*the_iterator); 
      A_COMMAND* a_command = dynamic_cast<A_COMMAND*>(*it); //line that is throwing the error 
      //string symbol = a_command->get_symbol(); 
      //cout << "symbol: " << symbol << endl; 
      //perform binary conversion 
     } 
     /*else if(command.commandType() == "C") 
     { 
      string dest = command.get_dest(); 
     }*/ 
     //shouldn't be any L commands in symbol-less version 
     else 
     { 
      std::cout << "unexpected command value \n"; 
     } 
     parser.advance(); 
    } 

} 

這是我的Parser.h,它有關於向量的迭代器的相關信息。

#include "Command.h" 
#include <vector> 


class Parser { 
private: 
    std::vector<Command> commands; 
    std::vector<Command>::const_iterator command_it = commands.begin(); 
public: 
    Parser(std::vector<std::string>); 
    bool hasMoreCommands() //are there more commands in the input? 
    { 
     if(command_it != commands.end()) 
      return true; 
     else 
      return false; 
    } 
    void advance(){std::next(command_it);} //move to next command, should only work if hasMoreCommands returns false} 
    std::vector<Command>::const_iterator currentCommand(){return command_it;} 
    std::vector<std::string> translateCommands(); //convert commands into binary strings 

}; 

以下是錯誤我收到:

g++ -O0 -g3 -Wall -c -fmessage-length=0 -std=c++11 -o Assembler.o "..\\Assembler.cpp" 
..\Assembler.cpp: In function 'void translateLines(Parser, Code)': 
..\Assembler.cpp:32:55: error: cannot dynamic_cast 'it.__gnu_cxx::__normal_iterator<_Iterator, _Container>::operator*<Command*, std::vector<Command> >()' (of type 'class Command') to type 'class A_COMMAND*' (source is not a pointer) 
    A_COMMAND* a_command = dynamic_cast<A_COMMAND*>(*it); 
                ^

任何線索有什麼錯嗎?

編輯:所以我現在看到,我不能使用命令的向量,而是我需要指針的命令。我已經改變了Parser.h來處理vector<Command*>而不是vector<Command>。對於輸入我想是這樣的:

A_COMMAND command(); 
commands.push_back(&command); 

但是,這不是很爲我工作,爲向量期待的指針,而不是引用。創建一個指向內存的指針並將其推入向量最簡單的方法是什麼?

+0

錯誤消息提示'Command'是一個類名。這意味着你的整個想法是註定的。給派生類的'dynamic_cast'將總是失敗,因爲你的向量只包含精確的'Commands',而不是任何派生類型的對象。如果你想容器'包含'共享一個基類的不同類型的對象,容器必須是一個指針的容器 –

+0

好吧,廢話,謝謝。 – Araganor

回答

3

你有一個vector of Command s。你不能投CommandA_COMMAND*。重要的是要注意,vector<Command>不可能包含A_COMMAND。如果你想在C++中做運行時多態性,你必須使用指針或引用。在這種情況下,您的Parser::commands需要爲std::vector<Command*>(或某種類型的智能指針,如std::vector<std::shared_ptr<Command>>)。

採取例如以下代碼:

std::vector<Command> commands; 
A_COMMAND a_command; 
commands.push_back(a_command); 

commands不包含A_COMMAND對象。它包含一個Command對象,它是a_command的副本。它更多或更少的這種equivilant:

std::vector<Command> commands; 
A_COMMAND a_command; 
Command temp(a_command); 
commands.push_back(temp); 

記住,在C++中的變量是一個對象,而不是一個對象的引用像在一些其他語言(Java或C#爲實例)。對象將不會改變類型,但可以具有一種類型的指向派生類型的對象的引用或指針:

std::vector<Command*> commands; 
A_COMMAND a_command; 
commands.push_back(&a_command); 

在這種情況下commands[0]Command*,但它指向一個A_COMMAND對象。

RE您的編輯:
您正在添加一個指針。 &some_variable返回一個指向some_variable的指針,但絕對不要這樣做。只要command超出範圍,它就會被銷燬,任何對它的訪問都會導致未定義的行爲。您將需要使用動態內存分配new。最好使用像std::shared_ptr<Command>這樣的智能指針類來保存動態分配的對象,以便以後不必擔心delete

如果使用原始指針,然後像這樣將工作:

A_COMMAND* command = new A_COMMAND; 
commands.push_back(command); 

如果用這種方法去,你需要delete所有的命令,當你與他們所做的(可能Parser的破壞者):

for(Command* command : commands) { 
    delete command; 
} 

儘管使用std::shared_ptr s會更好。聲明commandsstd::vector<std::shared_ptr<Command>> commands;,則:

std::shared_ptr<A_COMMAND> command = std::make_shared<A_COMMAND>(); 
commands.push_back(command); 

那麼你的對象都將自動當最後shared_ptr他們超出範圍得到delete版。如果你使用智能指針,你需要稍微改變它們。看看std::dynamic_pointer_cast

+0

那麼我應該怎麼處理呢?我需要能夠確定迭代器訪問哪種類型的命令。 – Araganor

+0

你已經知道它是什麼類型的命令,因爲你已經聲明它是'Command'類型的對象。它不可能是任何其他類型。 –

+0

我認爲使用劇組的全部觀點是檢查我從基類中得到的派生類是什麼類型的?解析器具有3種不同類型的命令(A_COMMAND,C_COMMAND和L_COMMAND),它們都是從Command中派生出來的。你在說,因爲我叫了一個向量,所以我不可能把它們轉換成子類型。那麼在那種情況下,我想我被搞砸了? – Araganor

-1

嘗試(它),而不是(*吧) 迭代器應該是一個指向對象的媒體鏈接,所以你需要省略*因爲這將導致在實際數據未參考

+1

iteratir可能不是一個指針;你會寫'&* it'來保證一個指針 –

0

真正的問題是爲什麼要使用dynamic_cast。 這是一個虛擬方法的工作。 如果派生了另一個類,那麼dynamic_cast也需要更新,而虛擬方法不需要關心派生類是什麼,只是它覆蓋了虛方法,可以使用接口類for基礎(純虛擬方法,無狀態)。這聽起來像是一個戰略模式的應用程序。 https://en.wikipedia.org/wiki/Strategy_pattern