polymorphism

Am I able to do this at all?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <cstring>

class thing{
public:
	thing();
	virtual ~thing();
	
	void setName(char *name){strcpy(m_Name,name);}
	char* getName(void){return m_Name;}
	
	
	protected:
	char m_Name[20];
	
};

class fromThing: public thing{
public:
	fromThing();
	virtual ~fromThing();
	
	void setDisc(char *name){strcpy(m_Disc,name);}
	char* getDisc(void){return m_Disc;}
	
	protected:
	char m_Disc[50];
};

int main(){
	thing* myThing = new fromThing();
	
	myThing.setName("myThing");
	myThing.setDisc("its My Thing");
	
	return 0;
}


or do i have to do this:
fromThing* myThing = new fromThing();
and not have any polymorphic functionality?

also why is it that when i change it to fromThing myThing = new fromThing(); (or its actual equivalent, as this is just a simplified example of what i want to do.)
g++ tells me
1
2
3
4
5
 g++ -Wall -I src -I src/game -o build/0.1/zlg src/main.cpp
/tmp/ccGVZQx8.o: In function `main':
main.cpp:(.text+0x30): undefined reference to `room::room(char const*)'
main.cpp:(.text+0x49): undefined reference to `thing::setDisc(char const*)'
main.cpp:(.text+0x5c): undefined reference to `thing::setVDisc(char const*)'

it doesnt have line numbers, but im guessing that its complaining cause those fuctions are actually declaired as room::room(const char *)

are strings that you enter in a functions parameters (like func("this");) always considered char const *

did this post make any sense?
Last edited on
1.arrays are declared char m_Name[20] ,not char [20]m_Name like you wrote in lines 10 and 22.

2."new" creates a pointer to an object so you should use thing* instead of thing.

3.you have to make functions setName and setDisc public or you will only be able to use them in friend and member functions of thing .

4.You can store derieved classes into base class pointers but then you wont be able to access members of derieved class.

5.You have to define functions before calling them( add {}).

after these changes program works fine for me.
Hope it helps.
Last edited on
http://www.cplusplus.com/doc/tutorial/polymorphism.html

Also, don't say

thing myThing = new fromThing();

it's

thing *myThing = new fromThing;

(think that's what hamsterman meant in (2).
lol. i should have proof read that but i still feel stupid for asking.

your forth point answers my question and now im asking myself why i asked in the first place. lol.

in any case, ive changed my code a bit

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
 
#include <cstring>

class thing{
    public:
        thing();
        virtual ~thing();

        void setName(char *name){strcpy(m_Name,name);}
        char* getName(void){return m_Name;}

        virtual void setDisc();
        virtual char* getDisc();

    protected:
        char m_Name[20];

};

class fromThing: public thing{
    public:
        fromThing();
        virtual ~fromThing();

        virtual void setDisc(char *name){strcpy(m_Disc,name);}
        virtual char* getDisc(void){return m_Disc;}

    protected:
        char m_Disc[50];
};

int main(){
    thing* myThing = new fromThing();

    myThing->setName("myThing");
    myThing->setDisc("its My Thing");

    return 0; 
}

and im getting

1
2
3
4
g++ lol.cpp 
lol.cpp: In function ‘int main()’:
lol.cpp:35: error: no matching function for call to ‘thing::setDisc(const char [13])’
lol.cpp:11: note: candidates are: virtual void thing::setDisc()


so im guessing that if i declare a virtual function i have to over ride it exactly, so i have to over ride
 
virtual void setDisc()=0;


with

 
virtual void setDisc(){strcpy(m_Disc,name);}


instead of

 
virtual void setDisc(char *name){strcpy(m_Disc,name);}


well, thanks for the help. its always an interesting feeling realising how stupid one can be sometimes.

in any case. my other question remains. if i fix up the code to look like this
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <cstring>

class thing{
    public:
        thing();
        virtual ~thing();

        void setName(char *name){strcpy(m_Name,name);}
        char* getName(void){return m_Name;}

        virtual void setDisc();
        virtual char* getDisc();

    protected:
        char m_Name[20];

};

class fromThing: public thing{
    public:
        fromThing();
        virtual ~fromThing();

        virtual void setDisc(char *name){strcpy(m_Disc,name);}
        virtual char* getDisc(void){return m_Disc;}

    protected:
        char m_Disc[50];
};

int main(){
    fromThing* myThing = new fromThing();

    myThing->setName("myThing");
    myThing->setDisc("its My Thing");

    return 0; 
}


i get this from g++

1
2
3
4
 g++ lol.cpp 
/tmp/ccAyN3vk.o: In function `main':
lol.cpp:(.text+0x28): undefined reference to `fromThing::fromThing()'
collect2: ld returned 1 exit status


which is interesting cause i thought it was going to give me undefined ref to 'setName(char const*)'

anyway, whats happening there?
As I've said: you have to define functions before using them.
which is interesting cause i thought it was going to give me undefined ref to 'setName(char const*)'

why? setName if defined in thing and inherited from it.

I dont understand why do you use so many virtual functions. You realy dont need virtual destructors becouse they cant be inherited. You dont need functions setDisc and getDisc in class this at all unles you intend to create an object of that class. You also dont need keyword virtual before function setDisc and getDisc unles you are going to write a class derieved from fromThing and redefine them.

You can find it all in http://www.cplusplus.com/doc/tutorial/polymorphism.html and http://www.cplusplus.com/doc/tutorial/inheritance.html
You realy dont need virtual destructors

Why not?
becouse they cant be inherited

Can other functions? I always thought it was a class concept.
On the other hand, if you have a base class without a virtual destructor, the base-classes destructor won't be called if a derived classes destructor gets called which is a Bad Thing. I think the committee made an error when they decided that the default constructor is not 'virtual' (they could have provided the possibility to override the virtaul default destructor with a non-virtual implementation). You have to provide your own implementation, even if it's empty (which you should *always* do - remember, it is still legal C++ code if you don't (meaning: it compiles), but your objects won't be destructed properly if you inherit from them).

By the way, use std::string instead of char arrays (what happens if your "name" gets larger than 20?) if you don't have very good reasons not to (which you most likely don't). And prefer "private" to "protected" member variables and use getter and setter functions (what you did anyways). That way, validity checking (if needed sometime) has to be done only once and is consistent for all derived classes (e.g., in your implementation you would have to check if the char-arrays are large enough. With a setter function this has to be implemented only once)
quote from "Friendship and inheritance"
What is inherited from the base class?
In principle, a derived class inherits every member of a base class except:

its constructor and its destructor
its operator=() members
its friends


Im confused now. Do inherited virtual functions call their base class versions when used?
Do inherited virtual functions call their base class versions when used?

No (if not explicitly called, that is) - except for the constructor and the destructor, provided that the latter is virtual. (That is, by the way, one of the reasons why you should not inherit from stl containers).

Edit. To clarify, try:
1
2
3
4
5
6
7
8
9
10
11
12
class A
{
  public:
    A()
    {
      std::cout<<"A constructed"<<std::endl;
    }
    ~A()
    {
      std::cout<<"A destroyed"<<std::endl;
    }
};

... same with B and virtual destructor
now write a C and D which inherit from A/B and print a similar message. Create an C/D object and look what happens.
Last edited on
why? setName if defined in thing and inherited from it.

cause this is an example program for the point of keeping my post short, which it really didnt succeed at. (which i ment to point out but may not have, whoops. )
its for the most part the same as what im actually trying to compile however having less functions and thats what its complaining about in my other one where im doing things the same.

(well i dont have virtual written all through my other files but otherwise its the same, hence the fourth point in the first .)

in any case. i think im slowly working out the linker issues.... im now getting whilst trying to compile that example program that i wrote for this thread. (i replaced the ; after the constructors and destructors with {})
1
2
3
4
5
6
7
8
g++ lol.cpp 
/tmp/cc235eL6.o: In function `thing::thing()':
lol.cpp:(.text._ZN5thingC2Ev[thing::thing()]+0x4): undefined reference to `vtable for thing'
/tmp/cc235eL6.o: In function `thing::~thing()':
lol.cpp:(.text._ZN5thingD2Ev[thing::~thing()]+0x7): undefined reference to `vtable for thing'
/tmp/cc235eL6.o:(.rodata._ZTV9fromThing[vtable for fromThing]+0x10): undefined reference to `thing::setDisc()'
/tmp/cc235eL6.o:(.rodata._ZTI9fromThing[typeinfo for fromThing]+0x8): undefined reference to `typeinfo for thing'
collect2: ld returned 1 exit status

man i really have broken it.
Last edited on
@arathalion
post your newest version

@exception
I guess my compiler doesnt like virtual constructors: it says
.\test.cpp(11) : error C2633: 'B' : 'inline' is the only legal storage class for constructors
but I get the point.
thanks for the info
Last edited on
lol. so i deleted the
1
2
     virtual void setDisc();
        virtual char* getDisc();


in thing and it works.

hamsterman: are you making the constructors virtual? if so try making only the destructors virtual.

like this
1
2
3
4
5
6
7
8
9
10
11
class B{
  public:
    B()
    {
      std::cout<<"B constructed"<<std::endl;
    }
    virtual ~B()
    {
      std::cout<<"B destroyed"<<std::endl;
    }
};
Last edited on
Topic archived. No new replies allowed.