1

I am trying to access a method of derived class from the object of my base class. I have a base class CBase which is an abstract class,

    class CBase{
protected:
    char path[255];
public:
    virtual void StartBackup()=0;
    void setpath(char * path)
    {
        strcpy(this->path,path);
    }
    virtual void afunc()
    {
        printf("Base\n");
    }

};

Now two classes Ctype1 and Ctype2 are derived classes from CBase

    class CType1:public CBase{
public:
    void StartBackup()
    {
        printf("Type1:%s",path);
    }
    void afunc()
    {
        printf("CType1:afunc\n");
    }
    void myfunc()
    {
        printf("myfunc\n");
    }
};

class CType2:public CBase{
public:
    void StartBackup()
    {
        printf("Type2:%s",path);
    }
    void afunc()
    {
        printf("type2:afunc\n");
    }
    void typefunc()
    {
        printf("typefunc\n");
    }
};

I have a class CManager which has an object of class CBase as its member,

    class CManager{
private:
    CBase * obj;
public:
    CManager(){
        obj = NULL;
    }
    ~CManager(){
        if(obj)
            delete obj;
        obj = NULL;
    }
    void inittype(int type)
    {
        if(type == 1)
        {
            obj = new CType1();
            obj->myfunc();
        }
        else
        {
            obj = new CType2();
            obj->typefunc();
        }

    }
};

In void inittype(int type) function i take the input as type and initialize the CBase object accordingly.

The problem that i am facing is that after creation of object when i try to access myfunc or typefunc i get compilation errors. How can i access these functions(I Dont want to create these functions in the base class)?

EDIT :

The errors that i get are,

  1. 'myfunc' : is not a member of 'CBase'
  2. 'typefunc' : is not a member of 'CBase'

Thanks

11
  • Consider using dynamic_cast Commented Oct 31, 2013 at 10:40
  • @Ali: The error is 'myfunc' : is not a member of 'CBase' Commented Oct 31, 2013 at 10:42
  • If you look at CBase, you can clearly see it isn't. You can delay assigning to obj, and use a CType* for all initialization code. Commented Oct 31, 2013 at 10:43
  • @BasileStarynkevitch : Is casting perfectly logical for doing this? Commented Oct 31, 2013 at 10:44
  • 1
    Why not declare a virtual void myfunc() = 0; in the base class? Commented Oct 31, 2013 at 10:45

3 Answers 3

3

If you only need to access the classes non-derived functions at creation time, then this will work

void inittype(int type)
{
    if(type == 1)
    {         
        CType1* temp = new CType1();
        temp->myfunc();
        obj = temp;
    }
    else
    {
        CType2* temp = new CType2();
        temp ->typefunc();
        obj = temp;
    }
}

If you need to access these member functions at other times, you'll need to use a cast - e.g.

CType2* child = dynamic_cast<CType2*>(obj);
Sign up to request clarification or add additional context in comments.

5 Comments

But if i have to call this function a 10000 times ,is it perfectly logical to use a cast each time??
Using the top example I provide, there's no casting going on, you're just keeping hold of the actual type long enough to use the member functions.
But if you're casting back to the child type multiple times in other places in your code, it's probably time to think about changing the design so that your classes have a consistent interface.
can you suggest how design change should be implemented(a few points)?
One would be to move any code from CType1::myfunc() into the constructor of CType1 and the code from CType2::typefunc() into the constructor of CType2, then you wouldn't need to call an additional function on creation. Without knowing how you're using these objects in other places, it's hard to suggest any other improvements
3

Create an inittype virtual function in your base class (doing nothing), then override it in the derived classes as you need.

void CType1::inittype() {
    myfunc();
}

void CType2::inittype() {
    typefunc();
}

void CManager::inittype(int type)
{
    if(type == 1)
    {
        obj = new CType1();
    }
    else
    {
        obj = new CType2();
    }
    obj->inittype();

}

4 Comments

There must be a way of stopping the if on a number to represent type. There must be a cleaner way. There must.
Right, but that's an other problem ... and not addressable based on the given context.
@doctorlove, as far as factories go, I don't think there is.
e.g. using templates on inittype
1

I'm not clear what you mean by "I Dont want to create these functions in the base class".

You appear to know about pure virtual functions. If you declared the problem functions as pure functions in CBase, you should be able to call them through a CBase * pointer.

One possible confusion in object-oriented languages is that "what type is this" has two answers depending on context. When you create a new object, the type is the exact type. When you access an existing object via a reference or pointer, the type is a set of possible types - the base class and all subclasses the might exist. More precisely, the type of the pointer/reference defines the interface you can use to access the object. That interface must be known without reference to the derived classes (which may not exist when the base class is compiled) so it must be declared in the base class - the virtual methods.

If you want to call something that's only known in the derived class, there are two options. One is to not forget the derived class in the first place. For example...

CType1 *temp = new CType1();
obj = temp;

temp->myfunc();

The other is to determine which derived class you're using at run-time, and use a cast to convert the pointer. The (relatively) safe way to do this is with dynamic_cast.

CType1 *temp = dynamic_cast<CType1> (obj);

if (temp)  {  temp->myfunc ();  }

I haven't covered how you identify the type at run-time. There's "Run-Time Type Identification" (RTTI) built into C++ to do this, but I've very rarely used it. In the rare cases where dynamic_cast is the right thing, I've always known the type for some other reason - either the objects were in a closed set of classes that could be identified via functionality in some interface anyway, or there was only one possibility that could occur in the code that needed the dynamic_cast.

The key words here are "closed set of classes" - if someone else inherits from your classes, you can have unexpected problems when objects of a type you don't know about and therefore cannot identify are accessed by your code. That isn't really a problem with OOP, it's a designed-in feature - you're supposed to be able to extend existing classes in OOP without notifying whoever wrote the base classes, that's what inheritance is for. Though in languages where you can mark a class final, that's probably a good idea if you don't want to allow it in this case (and IIRC C++11 provides a way to do that, I just don't know how to spell it).

2 Comments

that means i dont want to declare these functions in base class as there are many more such functions.
@singh - maybe you need a design pattern that replaces functions with classes, such as the command pattern or the strategy pattern?

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.