2

I am after your opinion on how best to implement an inheritance pattern in C++. I have two base classes, say

class fooBase{
protected:
    barBase* b;
};

class barBase{};

where fooBase has a barBase. I intend to put these classes in a library, so that wherever I have a fooBase it can use its barBase member.

I now intend to create a specialisation of these in a specific program

class fooSpec : public fooBase{};
class barSpec : public barBase{};

Now I want fooSpec::b to point to a barSpec instead of a barBase. I know that I can just initialise b with a new barSpec, but this would require me to cast the pointer to a barSpec whenever I wanted to use specific functions in the specialisation wouldn't it?

Is there another way that this is often acheived?

Cheers.

2
  • Please don't use pointers. Commented Jul 2, 2013 at 14:40
  • 1
    @Bartek He has to use pointers to facilitate the subtype polymorphism. The oft-repeated "never use pointers" opinion is misguided and uninformed. Commented Jul 2, 2013 at 15:00

6 Answers 6

4

Create a method in your specclass to cast the b into the special version. That way instead of casting it all the time, it looks like a getter.

On the other hand OO is about programming towards interfaces and not objects. So what you are doing here looks like programming towards objects. But the is difficult to see as this example is purely theoretical.

Sign up to request clarification or add additional context in comments.

Comments

3

You may consider the template solution:

template <class T>
class fooBase{
protected:
   T* b;
};

and then use it as

class fooSpec : public fooBase<barSpec>{};

while ordinarily, the base would be used as fooBase<barBase>. Is this what you want?

Comments

2

Normally we create a function that has the cast and returns the pointer -- and use that instead of the member directly.

Comments

1

Now I want fooSpec::b to point to a barSpec instead of a barBase.

There's no such thing as fooSpec::b. b belongs to fooBase, and your new class fooSpec is a (specialization of) a fooBase. You can't change the fact that b, a fooBase member, is of type barBase. This is a property of all the instances of fooBase that you can't invalidate in the particular subset of instances concerned by your specialization.

I know that I can just initialise b with a new barSpec, but this would require me to cast the pointer to a barSpec whenever I wanted to use specific functions in the specialisation wouldn't it?

Yes and no. Yes, you need to do that cast; but no, you don't need to do it every time. You can encapsulated in a function of fooSpec.

Is there another way that this is often acheived?

Not that I'm aware of.

4 Comments

-1. You can have a pointer for a superclass pointing to an instance of a subclass. That is how subtype polymorphism is accomplished in C++.
@Sildoreth What you spotted is actually a badly expressed sentence from my part. Of course you can have fooSpec::b point to a barSpec instead of a barBase in runtime. I will reword my answer.
@Sildoreth Wait. The problem is that there is no such thing as "fooSpec::b". fooSpec inherits fooBase::b, which is a different thing.
(withdrew downvote) This may just be semantics, but even though b belongs to fooBase, I think you can still refer to it with fooSpec::b. Disclaimer: I've never tried it.
0

this would require me to cast the pointer to a barSpec whenever I wanted to use specific functions in the specialisation wouldn't it?

That depends on whether the method you are trying to invoke is defined in the superclass and whether it is virtual.

You need to cast the pointer before invoking a method if one of the following is true...

  1. The method belongs to the subclass only
  2. The superclass has an implementation of the method and the subclass's implementation does not override the implementation in the superclass. This amounts to a question of whether the function is a virtual function.

Comments

0

Avoid data members in non-leaf classes, use pure virtual getters instead. If you follow this simple rule, your problem solves itself automatically.

This also makes most non-leaf classes automatically abstract, which may seem like an undue burden at first, but you get used to it and eventually realize it's a Good Thing.

Like most rules, this one is not absolute and needs to be broken now and then, but in general it's a good rule to follow. Give it a try.

If it looks too extreme, you may try one of the design patterns that deal with dual hierarchies such as Stairway to Heaven.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.