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 )
Related
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.
I have a base class inherited with many subclasses. I need to define a new signature for an abstract method, which is mostly a wrapper. I tried this
class B {
public:
virtual void f() = 0;
void f(string msg) { /* print msg and call f() */ }
};
class D : public B {
public:
void f() override { /* implementatation */}
};
int main() {
D d;
d.f("msg");
}
But it doesn't compile and give the following error
error: no matching function for call to 'D::f(string)
My questions are:
Why cannot D::f(string) be resolved?
Why does any of the following fix the problem?
renaming f(string) to f2(string) (ugly)
defining D::f(string x) { B::f(x)} (ugly as it has to be defined in every subclasses)
removing the abstract method, B::f() (not acceptable)
Any better solution?
The issue is that you hid B::f(std::string) here:
class D : public B {
public:
void f() override;
};
When you call D.f("msg"), name lookup will find the one f() in D and stop looking. We first find the candidate functions then perform overload resolution. Since that one happens to take no arguments, you get the compile error.
If you want to use the other overload of f, you need to bring it into D as well, like so:
class D : public B {
public:
using B::f;
void f() override;
};
Now we have D::f() (the overridden virtual function) and D::f(std::string ) (which we brought in from B).
An alternative, trivial solution would be to simply rename one or the other function so you don't have this problem to begin with.
Are you using the NVI idoims? Such as:
class B {
public:
virtual void f() = 0;
void f(string msg) {
/* print msg and call f() */
std::cout << msg;
f();
}
virtual ~B() {}
};
Then you should as far as possible try to call the non-virtual member function from the base class (by reference or pointer), such as:
D d;
B& b = d;
b.f("msg");
The problem at hand is hard to describe so the code is placed up front for better clarity.
struct Base
{
int b;
virtual void foo(){cout << b << endl;}
Base(int x) : b(x){}
};
struct Derived1 : Base //not virtual
{
virtual void foo(){/*Derived2's code*/}
Derived1() : Base(1){}
};
struct Derived2 : Base //not virtual
{
virtual void foo(){/*Derived2's code*/}
Derived2() : Base(2){}
};
struct MultiInheritance : Derived1, Derived2
{
void bar1()
{
//needs to access Derived1's Base foo()
}
void bar2()
{
//needs to access Derived2's Base foo()
}
};
Suppose that in some weird bizarre scenario, I would want a base class MultiInheritance that has two base classes Derived1 and Derived2 that have a common non-virtual base class Base.
There are two Base in MultiInheritance, how do I specify which Base class I wish to access in MultiInheritance?
The code above seems to work fine by casting several times, but I'm not sure if this is defined behavior or not. If it is, how is this implemented by the compiler to fulfill the needs of polymorphism? On one hand virtual calls should all result in the same virtual function table, but on the other if it does it wouldn't output different answers.
EDIT
I wish to emphasize that the Base classes are required to be non-virtual
EDIT2
Deep apologies, I seriously misrepresented myself. The code above is updated better reflects my original question.
This is known as the diamond problem.
http://www.cprogramming.com/tutorial/virtual_inheritance.html
If you want to keep base non-virtual and get the behavior you are seeking now, you can do this inside MultipleInheritance the following way to ensure you are calling the foo() function from the correct base class
struct MultiInheritance : Derived1, Derived2
{
void bar1()
{
Derived1::foo();
}
void bar2()
{
Derived2::foo();
}
};
Here's a more illustrative example.
#include <iostream>
using namespace std;
template <typename Res, typename Arg>
Res& as(Arg& arg)
{
return arg;
}
struct Base
{
virtual void foo() = 0;
};
struct Derived1 : Base {};
struct Derived2 : Base {};
struct MoreDerived1 : Derived1
{
void foo() { cout << "Derived1\n"; }
};
struct MoreDerived2 : Derived2
{
void foo() { cout << "Derived2\n"; }
};
struct MultiInheritance : MoreDerived1, MoreDerived2
{
void bar1() { as<Derived1>(*this).foo(); }
void bar2() { as<Derived2>(*this).foo(); }
};
int main ()
{
MultiInheritance m;
m.bar1();
m.bar2();
}
This example illustrates that:
You don't need to specify which Base you need explicitly using a full inheritance path, it is enough to go down to a subobject that has an unambiguous Base subobject
The virtual function mechanism works here. It would not work if you tried to call Derived1::foo().
The as helper function is just a syntactic sugar, you could just as well say
Derived1& d = *this;
d.foo();
There are two Base in MultiInheritance, how do I specify which Base
class I wish to access in MultiInheritance?
You have an ambiguity in which base-object you are calling in
void MultiInheritance::bar1(){
foo();
}
The way to resolve this is by telling the compiler where to look for foo.
void MultiInheritance::bar1(){
Derived1::foo(); // The same foo() as in your question.
}
This is what is accomplished by your
void MultiInheritance::bar1()
{
Derived1& d = *this;
This is described in the standard by §10.2.12. This is well defined. As is your chain of
void MultiInheritance::bar1()
{
Derived1& d = *this;
Base& b = *this;
by the same paragraph.
Unfortunately the scope resolution operator can't get you to jump from MultiInhteritance directly to Base as
MultiInheritance::foo(){
Derived1::Base::foo();
is describing a nested class Base.
To get to the foo() belonging to Base you use the scope resolution syntax in MultiInheritance, as well as in Derived1 and Derived2.
Derived1()::foo(){
Base::foo;
If this is inappropriate then the option you proposed is the option remaining.
If it is, how is this implemented by the compiler to fulfill the needs
of polymorphism? On one hand virtual calls should all result in the
same virtual function table, but on the other if it does it wouldn't
output different answers.
Compiler implementations differ by compiler, and as a commenter stated: Using vtables for virtual functions is an implementation detail. And if an implementation uses a vtable for virtual functions, the implementation need to take this scenario into account.
Why exactly doesn't this work? Are the inherited function signatures subtly incorrect or is the abstract base class enforced "before" the member functions are inherited or is it something else? Could this be convinced to work without function wrappers?
#include <iostream>
struct AbsBase {
virtual void foo() = 0;
virtual void bar() = 0;
};
struct ProvideFoo {
void foo() { std::cout << "foo\n"; }
};
struct ProvideBar {
void bar() { std::cout << "bar\n"; }
};
struct Concrete : public ProvideFoo, public ProvideBar, public AbsBase {
// I guess I could put function wrappers here... sigh...
//void bar() {ProvideBar::bar();}
//void foo() {ProvideFoo::foo();}
};
int main() {
Concrete c;
c.foo();
c.bar();
}
Why your code fails to compile
I think the downvoters are a bit harsh on you, as your reasoning to supply the implementations of the two pure virtual functions through separate classes has some intuitive appeal.
Alas, you are doing two unrelated things at the same time. ProvideFoo and ProvideBar are completly unrelated to the AbsBase abstract class. You could also subclass both of them from AbsBase, but then each of them would still be an abstract class. In either case, your current Concrete is an abstract class because it derives from at least one class with a pure virtual function. You can't create objects from such classes.
Fixing your code, part I
The easiest way is to drop subclassing from AbsBase altogether and subclass from ProvideFoo and ProvideBar directly. Of course, now you don't have virtual functions inside Concrete, so further subclassing can't easily override foo and bar functionality.
#include <iostream>
struct ProvideFoo {
void foo() { std::cout << "foo\n"; }
};
struct ProvideBar {
void bar() { std::cout << "bar\n"; }
};
struct Concrete : public ProvideFoo, public ProvideBar {};
int main() {
Concrete c;
c.foo();
c.bar();
}
Live Example I
Fixing your code, part II
You can also create multiple interfaces and multiple concrete implementations, something like this:
#include <iostream>
struct AbsFoo {
virtual void foo() = 0;
};
struct AbsBar {
virtual void bar() = 0;
};
struct ProvideFoo: AbsFoo {
void foo() { std::cout << "foo\n"; }
};
struct ProvideBar: AbsBar {
void bar() { std::cout << "bar\n"; }
};
struct Concrete : public ProvideFoo, public ProvideBar {};
int main() {
Concrete c;
c.foo();
c.bar();
}
Live Example II
Fixing your code, part III
Now for the encore: you can also use virtual inheritance when subclassing ProvideFoo and ProvideBar from AbsBase by using the virtual keyword
#include <iostream>
struct AbsBase {
virtual void foo() = 0;
virtual void bar() = 0;
};
struct ProvideFoo: virtual AbsBase {
void foo() { std::cout << "foo\n"; }
};
struct ProvideBar: virtual AbsBase {
void bar() { std::cout << "bar\n"; }
};
struct Concrete : public ProvideFoo, public ProvideBar {};
int main() {
Concrete c;
c.foo();
c.bar();
}
This is really advanced C++ and can become really complicated if your classes also contain member data. I would prefer to use the 2nd solution for your code.
Live Example III
I didn't make this clear in the question but I really did want to know literally why the code didn't compile. TemplateRex gave an awesome answer to the question as I asked it.
That said, here's an explanation of why the code doesn't compile and but also doesn't complain about an ambiguous member name. First, here's something similar that does compile.
struct A {
virtual void foo() { std::cout << "A::foo()\n"; };
};
struct B {
void foo() { std::cout << "B::foo()\n"; }
};
struct C : public A, public B {};
int main() {
// This is fine.
C c;
// Uncommenting the next line would cause an ambiguous member name lookup and
// invalidate the program.
//c.foo();
}
Fortunately, our program is not necessarily ill-formed just because an ambiguous name lookup can occur. Our program is ill-formed if an ambiguous name lookup does occur. 10.2.7
It is possible to create a valid program with c.foo() uncommented by adding even more definitions of foo().
// Name lookup never proceeds to the base classes if it succeeds locally. 10.2.4
struct C : public A, public B {
void foo() { std::cout << "C::foo()\n"; }
};
Changing A to an abstract class by making A::foo() a pure virtual function prevents compilation.
struct A {
virtual void foo() = 0;
};
struct B {
void foo() { std::cout << "C::foo()\n"; }
};
struct C : public A, public B {};
int main() {
// This is illegal.
C c;
// The next line is irrelevant.
//c.foo();
}
The compiler error indicates that struct C is abstract. Why? Let’s start with exactly what it means to be an abstract class.
"10.4 Abstract classes
2 An abstract class is a class that can be used only as a base class of some other class; no objects of an abstract class can be created except as subobjects of a class derived from it. A class is abstract if it has at least one pure virtual function.
"
Apparently C has at least one pure virtual function and so is an abstract class and we can only inherit from it. Before getting to why C has a pure virtual function, we can already answer part of the question. C is an abstract class and we tried to create an instance, that's illegal. Simply creating the object is illegal. It doesn’t matter if you never try to access a pure virtual function.
So why does C have a pure virtual function? It must be A::foo(). What happened to B::foo()? Did A::foo() somehow take priority?
First, we usually say derived classes “have” functions they inherit but this obscures what's really going on.
"
10.1.4 [...] For each distinct occurrence of a non-virtual base class in the class lattice of the most derived class, the most derived object (1.8) shall contain a corresponding distinct base class subobject of that type. […]
"
Here it’s made clear that a derived class and base class remain distinct. We don't merely inherit a pile of functions. Now the difference between overriding a member and having access to more than one identically named members is clear. We can inherit multiple functions with identical names and signatures. We can even refer to the separate functions if we’re careful with scope but an ambiguous name lookup is illegal.
To not be an abstract class, inherited pure virtual functions must be overridden. We are indeed inheriting a pure virtual function that is not being overridden and so we have an abstract class. Incidentally we’re also inheriting a non-pure virtual function with an identical signature, but that’s just irrelevant trivia.
I have a linked list of Foo objects. Foo is a base class, which has several classes inherit from it. Say, classes A, B, and C.
I am cycling through this linked list and calling a method some_method, which has 3 definitions; one for each child class:
some_method(A a);
some_method(B b);
some_method(C c);
The linked list is generic, so it is of type Foo, as it has an assortment of A, B and C objects.
When I'm cycling through the linked list at current_element, calling some_method(current_element);, how can I make it call the right method? The compiler complained until I wrote a some_method that took the generic Foo, and it only calls into that method.
Depending on your requirements, you may want to consider using polymorphism. To do this, add a pure virtual method to your base node class, and move the corresponding methods to the derived classes.
class Foo
{
public:
virtual void some_method() = 0;
};
class A : Foo
{
public
virtual void some_method()
{
// move the body of some_method(A a) here
}
};
For this to work, your linked list will need Foo*, instead of Foo.
class Node
{
public:
Foo* foo;
Node* next;
};
// ...
Node* someNode = GetNode();
// Calls correct method - A::some_method, B::some_method, or C::some_method
someNode->foo->some_method();
If you can't put some_method in Foo/A/B/C, then you might want to look into the Visitor design pattern:
http://en.wikipedia.org/wiki/Visitor_pattern
This is the "double dispatch" problem. You can use the visitor pattern. Usually the Visitor is a base class so you can re-use this design for multiple problems.
#include <iostream>
class FooVisitor;
class Foo
{
public:
virtual void some_method() = 0;
virtual void visit(FooVisitor* v) = 0;
};
class A;
class B;
class FooVisitor
{
public:
virtual void visit(A* a){ std::cout << "A" << std::endl;}
virtual void visit(B* b){std::cout << "B" << std::endl;}
};
class A : public Foo
{
public:
virtual void some_method()
{
// move the body of some_method(A a) here
}
virtual void visit(FooVisitor* v) { v->visit(this);}
};
class B : public Foo
{
public:
virtual void some_method()
{
// move the body of some_method(A a) here
}
virtual void visit(FooVisitor* v) { v->visit(this);}
};
int main()
{
FooVisitor fv;
Foo* f1 = new A;
f1->visit(&fv);
Foo* f2 = new B;
f2->visit(&fv);
getchar();
}
Two ways:
1) the better way:
Reverse your design such that someMethod is a virtual method of the base class Foo and redefine it in the derived classes. As:
class Foo {
public:
virtual void someMethod() = 0;
};
class A {
public:
void someMethod() { /* implementation specific to A here */ };
};
class B {
public:
void someMethod() { /* implementation specific to B here */ };
};
class C {
public:
void someMethod() { /* implementation specific to C here */ };
};
Then calling the someMethod on a pointer to Foo will automatically call the method from the appropriate class. If that cannot be done because someMethod cannot be implemented as part of Foo or its derivatives (e.g. it needs access to private members of the class it is currently in in your design), then you might try to split this functionality apart into subproblems that can be put into virtual methods of these classes A B C.
2) the "I don't have a choice" way:
Use RTTI (Run-Time Type Identification), it is included in C++. It requires that your base class Foo has at least one virtual method. You need to #include <typeinfo>, then use typeid() on the pointer, it will return a type_info object, and you can compare its name() result with the class names A B and C. This isn't a very nice approach because it has more overhead and it breaks OOP design principles. But if that's the only option, it's fine.
RTTI is your friend here. The example given in the link will guide you further
You can call the method for the child class as a member method. For exampleA a = new A(); a.some_method() should call the correct the method. Within some_method() you can reference to object using keyword this.