[SOLVED] Access inherited member from base class? (C++)
ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
I have a problem. This class is a base class for a basic enum handler:
Code:
#define ENUMOBJECT_BEGIN_ELEMENTS enum Element {
#define ENUMOBJECT_END_ELEMENTS ElementCount, DefaultElement, NoElement };
struct EnumObject
{
ENUMOBJECT_BEGIN_ELEMENTS
/* Just default elements defined by macro... */
ENUMOBJECT_END_ELEMENTS
EnumObject();
...
EnumObject& operator =(Element e);
...
private:
Element __ELEMENT__;
};
This is a base class that is meant to be inherited, like this:
Code:
class Enum : public EnumObject
{
public:
ENUMOBJECT_BEGIN_ELEMENTS
EnumElement1,
EnumElement2,
...,
ENUMOBJECT_END_ELEMENTS
};
However, when I run into code like this...
Code:
Enum e;
e = Enum::EnumElement1;
...obviously there is a problem, since the inherited member function "EnumObject& operator =(Element e);" is from "EnumObject" and does not recognize "Enum" members (this makes sense).
However, is there a way that I could use a base class to modify an inherited class's data?
The thread name itself suggests you are trying to do a wrong thing. I.e. base classes are not supposed to know their children. I.e. your overall design/architecture appear to be wrong.
Is there a way that I could use a base class to modify an inherited class's data?
This sentence describes polymorphism.
Code:
class Base
{
public:
int x;
virtual void initialize();
};
void Base::initialize()
{
x = 1;
}
class Derived: public Base
{
public:
int y;
void initialize();
};
void Derived::initialize()
{
Base::initialize();
y = 1;
}
Base *base = new Derived();
ptr->initialize();
delete base;
Presto. The base class has modified the inherited class' data.
I hate the excessive use of #define in your first version. But the far more excessive abuse of #define in the second version is far worse.
When you want to do something like that with #define, you can almost always do something better with templates.
Quote:
Originally Posted by cbh2000
However, is there a way that I could use a base class to modify an inherited class's data?
The most powerful way to do that is for the base class to be a template which takes the derived class as its template parameter.
When you first see this, it will look impossibly circular. But C++ allows it and C++ compilers handle it correctly and it is a very powerful method to inject common functionality into multiple classses even when that functionality must be customized to each class.
To make this easier for you to understand, I'll leave in the ugly #defines of your first version.
I'm not taking the time to test this, so there might be a few details wrong. I've used this approach many times, so the approach is valid even if some details are wrong
Indeed! I had just come to the same solution myself, and was about to go to bed after congratulating myself but stumbled upon your reply while checking my email.
Code:
template<typename Inherited>
struct EnumBase
{
enum Element
{
Count,
Default,
None
};
EnumBase(Inherited::Element e = None);
private:
Element e;
};
However, I really like your idea of using the base's functions as the inherited's. Thank you!
Quote:
I hate the excessive use of #define in your first version. But the far more excessive abuse of #define in the second version is far worse.
Is there some purpose to defining enum Element{...} in the base class? So far as I understand, you never want to use that version of Element. I think my approach: typedef typename Actual::Element Element;
is much more effective, because it makes Element in the base class be the actual type of Element in the actual class.
With your version of Element in the base class, what is the purpose of private: Element e;
That Element is the wrong type to use for values of Actual::Element
What compiler are you using? I don't think the following line of your code is valid: EnumBase(Inherited::Element e = None);
Older compilers will recognize that Inherited::Element is a type name and be able to parse that, but the C++ standard says they shouldn't, so newer compilers should not be able to parse that. Also, you have made None the wrong type, so that shouldn't compiler either.
But I am impressed you thought of the main idea of inheriting from a base class that is templated by the inherited class. Had you seen that trick before? I would never have started using that myself if I hadn't seen it in other code. I would have assumed it was too circular to compile.
Actually, yes, I do want to use the base class' Element enum, because only then may I provide two default elements: "None" (Unassigned) and "Default" without having to provide them in the inherited class.
I didn't compile the code when I put it here (I encountered the problems you have mentioned and fixed them when trying to compile), and I'm using GCC 4.5. And, you are right, it won't compile:
Code:
../untitled/enumobject.h: In instantiation of ‘EnumObject<Enum>’:
../untitled/enumobject.h:20:1: instantiated from here
../untitled/enumobject.h:7:38: error: invalid use of incomplete type ‘class Enum’
../untitled/enumobject.h:19:7: error: forward declaration of ‘class Enum’
Ugh!
I'm becoming frustrated with C++'s lack of ingenuity... Is there a way to force the compiler to define Enum later? (extern keyword only works on variables or functions.)
I'm tempted to create my own preprocessor, but it wouldn't be "standards compliant."
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.