1

I have the following code:

class Official {
    public:
        explicit Official(int iRow, int iColumn, int iRankHolder, int** aiBoardHolder);
};

class General : public Official {
    public: 
        explicit General(int iRow, int iColumn, int iRankHolder, int** aiBoardHolder) : Official(iRow, iColumn, iRankHolder, aiBoardHolder) {};
};

class Map {
    private:
        std::vector<Official> aoOfficialStack;

    public:
        void generateOfficialObject();
};

void Map::generateOfficialObject() {
    aoOfficialStack.push_back(General(1, 2, 3, aiBoardPosition));
}

Question is why am I getting this error after calling generateOfficalObject()?

Error C2664 'void std::vector>::push_back(const Official &)': cannot convert argument 1 from 'General' to 'Official &&' Project c:\users\user\desktop\project\project\board\board.cpp 12

Thank you very much!

Redis1001
  • 157
  • 15
  • 1
    This is not the code producing the error you're showing. `FiveStarGeneral` is missing a return type (since it's not a constructor, the class name is different). Please post the real code. And anyway, look up Object Slicing; you will see that what you're trying to achieve cannot work as-is. – Angew is no longer proud of SO Sep 28 '16 at 14:09
  • sorry. i already edited the code.. that was a miss. this is now the real code and the real error. sorry guys – Redis1001 Sep 28 '16 at 14:10
  • 1
    Even if your code compiled, it likely wouldn't do what you expected. See [object slicing](http://stackoverflow.com/q/274626/2069064). – Barry Sep 28 '16 at 14:10
  • 1
    Your program compiles just fine [here](http://coliru.stacked-crooked.com/a/9333bd90fac38b37). – eerorika Sep 28 '16 at 14:12
  • I'm using visual studio 2015 and the error is what i posted above. – Redis1001 Sep 28 '16 at 14:14

2 Answers2

1

Your example program compiles. Either your example is incomplete, or your compiler isn't standard compliant.

The program is well formed and has defined behaviour. The behaviour might not be what you expect however. Object slicing is an obscure language feature that beginners may find counterintuitive. It makes no sense to create an instance of General, if you're only going to use the Official sub object. Ask yourself: why not create an instance of Official in the first place?

eerorika
  • 232,697
  • 12
  • 197
  • 326
  • 1
    Correct answer. I think the example is incomplete. –  Sep 28 '16 at 14:18
  • Yes, sorry code is correct but inclusion of header files in other source files cause circular dependencies resulting to redefenitions and thus, the problem in visual studio. I already resolved this when I resolved the circular dependency. Thank you!! – Redis1001 Sep 28 '16 at 14:42
  • @Redis1001 always create a [mcve]. If your exmaple code doesn't reproduce the problem, then it isn't very useful. – eerorika Sep 28 '16 at 15:47
0

It's a c++ restriction. You cannot assign the value of a derived class to it's base class without consequences. This may compiles but will result in some unexpected behaviors. It could copy the object into an instance of the base class (this losing the information it has from the derived class). This is called object slicing

You have to use references or pointers for this. So you can change your vector to

std::vector<std::unique_ptr<Official>> aoOfficialStack;

and assign like:

aoOfficialStack.push_back(std::make_unique<General>(1, 2, 3, aiBoardPosition));

a shared_ptr would also be an alternative it depends on the usage.

Community
  • 1
  • 1
Hayt
  • 5,210
  • 30
  • 37
  • "You cannot change a derived class to a base class by value" is plain wrong (although it introduces object slicing) –  Sep 28 '16 at 14:20
  • Yeah I saw it compiles in gcc/clang. but it seems like not in VS. I was surprised this compiles without warnings though. I will edit this. – Hayt Sep 28 '16 at 14:21
  • If it does not compile with VS, this is a "bug" in VS. And there is no need for warning here, object slicing is not bad, you just have to be aware of it. – Holt Sep 28 '16 at 19:53