2

I have the following class hierarchy set up and would like the print() function of the non-singleton base object OtherBase to be called which in turn calls the printSymbol() from one of the child classes, in this case SingletonChild. I understand this is a complicated and somewhat unnecessary looking hierarchy and way of doing things but this is an assignment and I am required to do it in this way.

An example of my problem is as follows:

#include <iostream>
using namespace std;

class Object
{
    virtual void print() = 0;
};

class SingletonBase : public Object
{
private:
    static SingletonBase* theOnlyTrueInstance;
protected:
    SingletonBase()
    {
        if(!theOnlyTrueInstance)
            theOnlyTrueInstance = this;
    }
    virtual ~SingletonBase(){}
public:
    static SingletonBase* instance()
    {
        if (!theOnlyTrueInstance) initInstance();
        return theOnlyTrueInstance;
    }
    void print()
    { cout<<"Singleton"<<endl; }
    static void initInstance()
    { new SingletonBase; }
};

SingletonBase* SingletonBase::theOnlyTrueInstance = 0;

class OtherBase : public Object
{
public:
    virtual string printSymbol() = 0;
    void print()
    { cout<<printSymbol(); }
};

class SingletonChild : public SingletonBase , public OtherBase
{
public:
    string printSymbol()
    {
        return "Test";
    }
    static void initInstance()
    { new SingletonChild; }
};

int main() {
    SingletonChild::initInstance();
    OtherBase* test = (OtherBase*) SingletonChild::instance();
    test->print();
    return 0;
}

How can I get the instance test to call the print function of the one base class OtherBase and not the Singleton base class SingletonBase?

I have tried test->OtherBase::print(), but this did not work.

2
  • You just want your test object to call the OtherBase's print method instead of SingletonBase's? Commented Oct 3, 2016 at 13:49
  • @MuhammadAhmad Yes, thats pretty much it. Commented Oct 3, 2016 at 13:51

3 Answers 3

3

@MuhammadAhmad's answer is basically right. I would like to add that the main issue here is that a C-style cast is allowing you to do something that you really don't want to do. Because you can't statically cast a SingletonBase to an OtherBase, the C-style cast is doing a reinterpret_cast instead, and calling print() on the resulting pointer is undefined behavior. If you had used a static_cast, you would have gotten an error:

OtherBase* test = static_cast<OtherBase*>(SingletonChild::instance());

error: invalid static_cast from type ‘SingletonBase*’ to type ‘OtherBase*’

This may have led you to realize you needed to do things a bit differently. For example, you can use a dynamic_cast to cast sideways like this.

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

Comments

2

SingletonChild is inheriting it's instance method from SingletonBase, which is returning a pointer to SingletonBase.
So calling SingletonChild::instance(); will get you a SingletonBase*, which you can't simply cast to OtherBase*

Try casting it to SingletonChild* first, then to OtherBase*:

OtherBase* test = (OtherBase*)((SingletonChild*)SingletonChild::instance());

And then call the print method simply like this: test->print();

See the code on ideone.

EDIT:

You can also achieve this like this:

SingletonChild* test = (SingletonChild*)SingletonChild::instance();
test->OtherBase::print();

See this method in action too.

Comments

1

What you are trying to do is casting an object of type SingletonBase* to type OtherBase*, which is not possible because SingletonBase does not derive from OtherBase. If you had used dynamic_cast rather than old, deprecated C-style cast, you would have recognized this situation rather immediately.

To solve the issue, you need to modify the code as follows:

class Object
{
    virtual void print() = 0;
};

class SingletonBase : public Object
{
private:
    static Object* theOnlyTrueInstance;
protected:
    SingletonBase()
    {
        if(!theOnlyTrueInstance)
            theOnlyTrueInstance = this;
    }
    virtual ~SingletonBase(){}
public:
    static Object* instance()
    {
        if (!theOnlyTrueInstance) initInstance();
        return theOnlyTrueInstance;
    }
    void print()
    { cout<<"Singleton"<<endl; }
    static void initInstance()
    { new SingletonBase; }
};

Object* SingletonBase::theOnlyTrueInstance = 0;

class OtherBase : public Object
{
public:
    virtual string printSymbol() = 0;
    void print()
    { cout<<printSymbol(); }
};

class SingletonChild : public SingletonBase , public OtherBase
{
public:
    string printSymbol()
    {
        return "Test";
    }
    static void initInstance()
    { new SingletonChild; }
};

int main() {
    SingletonChild::initInstance();
    OtherBase* test = dynamic_cast<OtherBase*>(SingletonChild::instance());
    test->print();
    return 0;
}

You should avoid C-style casts, as you could end-up manipulating object like something they are not.

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.