I have the following class hierarchy:
class A
{
public:
virtual void func()
{
cout<<"A"<<endl;
}
};
class B: public A
{};
class C: public B
{
public:
virtual void func()
{
cout<<"C"<<endl;
}
};
class D: public C
{
public:
virtual void func()
{
//I don't want to use the class C's implementation
//So I should call the next base function: B::func()
//But since B does not re-define the virtual function, we might as well
//directly call A::func()
//But what is the correct practice? Call A::func() directly or call B::func()
//A::func();
//B::func();
}
};
int main()
{
A *ob;
D dob;
ob = &dob; ob->func();
return 0;
}
I don't want to use the class C's implementation
So I should call the next base function: B::func()
But since B does not re-define the virtual function, we might as well directly call A::func()
But what is the correct practice? Call A::func() directly or call B::func()
There's no real diffrence, since the B structure contains a copy of the A::func() itself - When a deriviate doesn't override the parent classes implementation, the function is copied. However, I believe casting the C object another time back to A from B would be less efficient, and thus I believe B::func() is the better way of the two.
Related
May be my question is wrong. I am new to C++.
Is there any way call a base class member function using derived class object if that function is being overridden in derived class?
For example:
class A {
public:
void add() { cout<<"A"; }
};
class B: public A {
public:
void add() { cout<<"B"; }
};
int main() {
B bObj;
bObj.add(); // calls member function of class B
return 0;
}
First of all, you aren't really overriding the add function, merely hiding the name, since A::add is not declared virtual.
To call A::add, just be explicit about it:
bObj.A::add();
Typically, B::add() exists for a reason and you probably shouldn't be calling A::add() on a B. Which isn't to say you can't - you just have to turn it into an A first:
B bObj;
static_cast<A&>(b).add(); // calls A::add()
Or explicitly specify that it's A::add():
bObj.A::add();
From within B, you have to qualify the call:
class B: public A {
public:
void add() { cout<<"B"; }
void test() {
add(); // calls B::add
A::add(); // calls A::add
}
};
So assume there is class A with function foo.
Class A is the parent of a few classes which all have the function foo.
All of the child classes need the functionality of
A::foo and adds upon it.
For example:
class A
{
public:
void foo()
{
print('A');
}
};
class B:public A
{
public:
void foo()
{
print("B");
}
};
class C:public A
{
public:
void foo()
{
print("C");
}
};
void main()
{
B b;
C c;
c.foo()// now only goes to C::foo(), meaning print C. I want it to to also go into A::foo() meaning print AC
b.foo()//now only goes to B::foo(),meaning print B. want it to print AB
}
And if I want to add class D : A with foo function it will also do A::foo() and then D::foo()
Sorry if I am missing something obvious.
EDIT : since it wasn't clear the question was if there is an automatic way to do so.
EDIT : found a workaround:
class A
{
virtual void foo2(){}
public:
void foo()
{
print('A');
foo2();
}
};
class B:public A
{
void foo2()
{
print("B");
}
public:
};
class C:public A
{
void foo2()
{
print("C");
}
public:
};
void main()
{
B b;
C c;
c.foo()// now prints AC
b.foo()//now prints AB
}
seems redundant since now there are 2 functions now.
You can call the parent class's implementation of a function using A::foo().
In your case, simply adding that function call will achieve the result you want:
class B:public A
{
public:
void foo()
{
A::foo();
print("B");
}
};
As a side note, whenever you intend to override functions, you should declare it as virtual:
class A
{
public:
virtual void foo()
{
print('A');
}
};
And then when overriding it, use the override keyword:
class B:public A
{
public:
void foo() override
{
print("B");
}
};
What you've called a workaround is an established solution to this question, and whilst some people might call it a workaround many wouldn't.
Its even got a name that covers it. The non-virtual interface pattern.
herb sutter :- http://www.gotw.ca/publications/mill18.htm
One example from S.O., there's probably more:-
Non-virtual interface design pattern in C#/C++
I'd argue that this IS a way to do it automatically.
As to your aside that its redundant because there are 2 functions - well there were 2 before (the base version and derived version).
One benefit of this approach in some designs is that if the virtual method foo2 is pure virtual (which would make A abstract) then this forces all immediate derived classes to implement foo2. (I say immediate because if B derives from A it must implement foo2 but if C then derives from B C isn't forced to implement foo2, it has access to B::foo2 )
Let's consider the following code:
#include <iostream>
class Base
{
public:
void foo() //Here we have some method called foo.
{
std::cout << "Base::foo()\n";
}
};
class Derived : public Base
{
public:
void foo() //Here we override the Base::foo() with Derived::foo()
{
std::cout << "Derived::foo()\n";
}
};
int main()
{
Base *base1 = new Base;
Derived *der1 = new Derived;
base1->foo(); //Prints "Base::foo()"
der1->foo(); //Prints "Derived::foo()"
}
If I have the above stated classes, I can call the foo method from any of Base or Derived classes instances, depending on what ::foo() I need. But there is some kind of problem: what if I need the Derived class instance, but I do need to call the Base::foo() method from this instance?
The solve of this problem may be next:
I paste the next method to the class Derived
public:
void fooBase()
{
Base::foo();
}
and call Derived::fooBase() when I need Base::foo() method from Derived class instance.
The question is can I do this using using directive with something like this:
using Base::foo=fooBase; //I know this would not compile.
?
der1->Base::foo(); //Prints "Base::foo()"
You can call base class method using scope resolution to specify the function version and resolve the ambiguity which is useful when you don't want to use the default resolution.
Similar (Not exactly same case) example is mentioned # cppreference
struct B { virtual void foo(); };
struct D : B { void foo() override; };
int main()
{
D x;
B& b = x;
b.foo(); // calls D::foo (virtual dispatch)
b.B::foo(); // calls B::foo (static dispatch)
}
May be my question is wrong. I am new to C++.
Is there any way call a base class member function using derived class object if that function is being overridden in derived class?
For example:
class A {
public:
void add() { cout<<"A"; }
};
class B: public A {
public:
void add() { cout<<"B"; }
};
int main() {
B bObj;
bObj.add(); // calls member function of class B
return 0;
}
First of all, you aren't really overriding the add function, merely hiding the name, since A::add is not declared virtual.
To call A::add, just be explicit about it:
bObj.A::add();
Typically, B::add() exists for a reason and you probably shouldn't be calling A::add() on a B. Which isn't to say you can't - you just have to turn it into an A first:
B bObj;
static_cast<A&>(b).add(); // calls A::add()
Or explicitly specify that it's A::add():
bObj.A::add();
From within B, you have to qualify the call:
class B: public A {
public:
void add() { cout<<"B"; }
void test() {
add(); // calls B::add
A::add(); // calls A::add
}
};
class A
{
public:
void test ()
{
cout<<"In A";
}
};
class B :public A
{
public:
void test ()
{
cout<<"In B";
}
};
class C : public B
{
public:
int c;
};
int main()
{
C c;
c.test();
}
The result is: In B...
No, it is not overriding, but rather hiding the original method.
Polymorphic behavior in C++ is restricted to the methods declared virtual, and each implementation of that method in a class hierarchy is called an override of the method.
struct base {
virtual void foo();
void bar();
};
struct derived : base {
virtual void foo();
void bar();
};
In the example base::foo and derived::foo are overrides. When you use a class of type derived through a pointer or reference of type base, the final override method will be called (the lowest one in the hierarchy: in this case derived::foo). The important point here is that the call is through a pointer or reference to base:
void test() {
derived d;
base &b = d;
b.foo(); // derived::foo() <- final overrider
b.bar(); // base::bar() <- non-virtual, no override
d.bar(); // derived::bar() <- hides the method in base
}
What happens in the case of bar (or in your case) is that when the compiler finds the call d.bar() it needs to determine what method to call. To locate the method it will first look inside derived declaration and it will find derived::bar() (which is unrelated to base::bar()) and it will use that method without checking higher in the class hierarchy. If you need to call the method higher in the hierarchy you can do it by either getting a reference to the higher type or fully qualifying the method you want to call.
Note that hiding does not only happen when the signature matches completely, but in all cases where the compiler finds a method with the same name:
struct base {
void bar();
};
struct derived : base {
void bar( int );
};
void test() {
derived d;
base & b;
b.bar(); // ok: base::bar()
d.bar(1); // ok: derived::bar(int)
//b.bar(1); // error: base has no bar method that takes an integer
//d.bar(); // error: derived::bar takes an integer, base::bar is hidden
d.base::bar(); // ok: fully qualifying tells the compiler where to look
}