Jump to content
  • Advertisement

Archived

This topic is now archived and is closed to further replies.

MENTAL

3 Very Tricky C++ Inheritence Questions

This topic is 5282 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

1. Can a pure virtual function (i.e one that has = 0 on the end) be overridden by an inherited class with a constant pure virtual function and still get called?
class cBaseClass
{
public:

    virtual void VirtualFunction () = 0;
};

class cInheritedClass : public cBaseClass
{
public:

    virtual void VirtualFunction () const
    {
        printf ("I'm a constant virtual function that overrided a pure virtual function!\n");
    }

};

cBaseClass *Foo = new cInheritedClass;
Foo->VirtualFunction ();
The last line should result in cInheritedClass::VirtualFunction being called, not cBaseClass::VirtualFunction. I'm hoping that a constant function is just a compiler directive to make sure nothing inside the class gets written too and doesn't effect inheritance. I'm using this in my level class for some of the collision routines, where it would be nice to specify if the function can modify the class on a per Object/Class basis. 2. Would the above work the other way around? declare a constant pure virtual function and override it with a non-constant one? (why you would ever want to do that I don't know, but I'm curious) 3. When passing an array of inherited classes to a pointer of the base class, will they be interated through properly?
class cBaseClass
{
public:

    int Foo;
};

class cInheritedClass : public cBaseClass
{
public:

    int Bar;
};

void BaseClassLoop (cBaseClass *List, int Count)
{
    int i;

    for (i = 0; i < Count; ++i)
        List[i].Foo = i;

    while (Count--)
    {
        List->Foo = i + 1;
        List++;
    }
}

cInheritedClass Array[400];

BaseClassLoop (&Array, 400);

Things to bear in mind is that cInheritedClass is twice the size of cBaseClass (two ints instead of one), meaning that the pointer or array increments might access cInheritedClass::Bar every other loop if the code doesn't detect the size of the class). And now the arguments begin... [edited by - mental on June 4, 2004 5:38:23 AM]

Share this post


Link to post
Share on other sites
Advertisement
At first, edit your post, you have to write [/source] after each code part!
To question one:
Yes, it''s possible, but your pure virtual function must also be declared as const!

class cBaseClass
{
public:

virtual void VirtualFunction () const = 0;
};

class cInheritedClass : public cBaseClass
{
public:

virtual void VirtualFunction () const
{
printf ("I''m a constant virtual function that overrided a pure virtual function!\n");
}

};


And here goes my text after the sourcecode. You see, it''s outside the box!

-------------------------


Oncer

Share this post


Link to post
Share on other sites
actually, i forgot to put in the / at the end of the first piece of source code so it thought i was defining another piece of code!

anyway, thanks for the speedy reply, but what i need to know is if you can have a non-constant PVF, and override it with a constant VF for one object, and keep it non-constant for another



class cBaseClass
{
public:
virtual void VirtualFunction () = 0;
};

class cInheritedClassConst : public cBaseClass
{
public:
virtual void VirtualFunction () const
{
printf ("I''m a constant virtual function that overrided a pure virtual function!\n");
}
};

class cInheritedClassNonConst : public cBaseClass
{
public:
virtual void VirtualFunction () // No const!!

{
("I''m a virtual function that overrided properly because I''m not trying to break the rules of C++!\n");
}
}



basically, can you override a non-constant PVF with a constant virtual function, WITHOUT changing the declaration of the original PVF?

Share this post


Link to post
Share on other sites
const is part of the functions signature and as such the non-const VirtualFunction in cInheritedClass is considered a seperate method so cInheritedClass cannot be instantiated

so basically to answer your question: NO.
But generally changing the "const-ness" of a method is a sign of bad design


[edited by - ChaosEngine on June 4, 2004 5:51:59 AM]

Share this post


Link to post
Share on other sites
1. the "const" is part of the function signature. So the two "VirtualFunction" you have are unrelated. You should obtain a compilation error if you try to instanciate a cInheritedClass object (pure virtual function not implemented)

3. You iterate in an array of pointers to your objects. Whether it is a cInheritedClass* of a cBaseClass*, your pointer is always the same size (32 bits on most PCs). So the ++ will work as you expect it to work.

[edit] pfff ... ChaosEngine just says the same a few seconds before. I'm too slow to type

[edited by - vprat on June 4, 2004 5:54:05 AM]

Share this post


Link to post
Share on other sites
quote:
Original post by vprat
3. You iterate in an array of pointers to your objects. Whether it is a cInheritedClass* of a cBaseClass*, your pointer is always the same size (32 bits on most PCs). So the ++ will work as you expect it to work.




Correct me if I'm wrong but I think he's iterating an array of objects, not an array of pointers.


cInheritedClass Array[400];






[edited by - Red Ant on June 4, 2004 6:03:35 AM]

Share this post


Link to post
Share on other sites
const functions have a different signature so in the base class you could have


class base {
public:
virtual void func() {
cout << "I''m not const\n";
}
virtual void func() const {
cout << "I''m const\n";
}
};


without any problems.

the override in a dervied class will only be called for the matching signature.

If you call func() on a constant object it will call the const version. If the const version doesn''t exist then the compiler won''t allow you to call the non-const version as it might not be safe safe.

If you call func() on a non-const object then it will call the non-const version. If the non-const one didn''t exist then the const one would be called (as it doesn''t hurt).

If you want to reuse code and call the const version from the non-const version the you could do the following, although its dubious as to whether it''s worth it as you could just completely get rid of the non-const version and everything would be fine. I guess it would only be useful if you weren''t able to do away with the non-const version such as if it was declared in a base class...


#include <iostream>

class base {
public:
virtual void func() const {
std::cout << "const base::func\n";
}
virtual void func() {
std::cout << "non const base::func\n";
}
};

class derived : public base {
public:
using base::func;
virtual void func() {
std::cout << "non const derived::func calling: ";
const derived& self = *this;
self.func();
}
};

int main() {
base b;
b.func();
derived d;
d.func();
return 0;
}


The tricky part is that redeclaring func in the derived class actually masks out the const version in the base class (I was surprised too!), so I''ve brought the base class versions into scope by putting a using declaration. If you get rid of it the the derived class can''t see the const version in the base class.

This is the only place you should use using in a header file by the way.

Share this post


Link to post
Share on other sites
Questions 1 and 2 have been answered.

Answer to question 3 (if i understand correctly what your asking)

3. When passing an array of inherited classes to a pointer of the base class, will they be interated through properly?


No, they won''t.

Your compiler thinks it is iterating through an array of cBaseClass instances.
So it will take steps of: sizeof(cBaseClass) where it should take steps of: sizeof(cInheritedClass).



Share this post


Link to post
Share on other sites
1 and 2: damn. I think i''ll just leave off the const and rely on my expertise (heh) to make sure I don''t write anything when it shouldn''t be written

3: I thought this would be the case (thanks Direct4D).

thank you for all your replies. If anyone ever puts together a C++ FAQ I think those 3 questions should be on it

Share this post


Link to post
Share on other sites
The problem is obviously circumvented easily by passing an array of base pointers (or better yet, a std::vector). As for the existance of a FAQ, there is the C++ FAQ Lite, and it is Good.

Share this post


Link to post
Share on other sites

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!