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");
Related
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 two classes A and B with the following interface:
class A {
public:
virtual void start() {} //default implementation does nothing
};
class B {
public:
void start() {/*do some stuff*/}
};
and then a third class which inherits from both, A publicly because it implements this "interface", and B privately because that's implementation detail.
However, in this specific implementation, start() only has to contain a call to B::start(). So I thought I could use a shortcut and do the following:
class C: public A, private B {
public:
using B::start;
};
and be done with it, but apparently it doesn't work. So I get using private base function doesn't work in order to override virtuals. From that, two questions:
Is there any way to make this work as I supposed it may have worked?
Why would the compiler accept this code as valid? As I see it there are now two start() functions with the exact same signature in C and yet the compiler seems fine with it and only calls A::start().
EDIT: A few precisions:
The goal is to manipulate C objects through A pointers.
I'm currently using a simple function that just calls B::start(), I was specifically wondering if a using declaration could indeed "override" a virtual, and if not, how this was allowed to have both functions coexist.
I might have omitted a few things like virtual inheritance for simplicity.
Is there any way to make this work as I supposed it may have worked?
You should override the member function and explicitly call B::start():
class C: public A, private B {
public:
void start() override { B::start(); }
};
Why would the compiler accept this code as valid? As I see it there
are now two start() functions with the exact same signature in C and
yet the compiler seems fine with it and only calls A::start().
You are right, there are two member functions accessible in C (A::start() and B::start()). And in class C, without overriding start() or making the start() of any of the base classes visible by doing a using ...::start(), you will have ambiguity error when trying to call the member function using unqalified namelookup from an object of C.
class A {
public:
virtual void start() { std::cout << "From A\n"; }
};
class B {
public:
void start() { std::cout << "From B\n"; }
};
class C: public A, private B {
};
int main(){
A* a = new C();
a->start(); //Ok, calls A::start()
C* c = new C();
c->start(); //Error, ambiguous
}
To fix that, you will have to use the qualified name such as:
C* c = new C();
c->A::start(); //Ok, calls A::start()
Now, doing a using B::start() in class C simply declares the start() to refer to B::start() whenever such name is used from an object of C
class A {
public:
virtual void start() { std::cout << "From A\n"; }
};
class B {
public:
void start() { std::cout << "From B\n"; }
};
class C: public A, private B {
public:
using B::start();
};
int main(){
A* a = new C();
a->start(); //Ok, calls A::start()
C* c = new C();
c->start(); //Ok, calls B::start()
}
using B::start makes the function void B::start() visible in C, it does not override it. To call make all the above unqualified member function call, to call B::start(), you should override the member function in C, and make it call B::start()
class A {
public:
virtual void start() { std::cout << "From A\n"; }
};
class B {
public:
void start() { std::cout << "From B\n"; }
};
class C: public A, private B {
public:
void start() override { B::start(); }
};
int main(){
A* a = new C();
a->start(); //Ok, calls C::start() which in turn calls B::start()
// ^^^^^^^^^^^^^^^^ - by virtual dispatch
C* c = new C();
c->start(); //Ok, calls C::start() which in turn calls B::start()
}
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)
}
I have stumbled on a problem while trying to re-use code from different classes. I post it here in hope that some of you might be able to help me.
I have a set of classes (B,C) deriving from the same class (A) which forces the implementation of some methods (foo, run). Class B implements these method, and both B and C provide other methods:
#include<iostream>
template<class I, class O>
class A {
public:
A() {}
virtual ~A() {}
virtual void foo() const = 0; // force implementation of this function
virtual void run() const = 0; // force implementation of this function
};
template<class I, class O>
class B : public A<I,O> {
public:
B() {}
virtual ~B() {}
virtual void foo() const { // implementation for the Base class
std::cout << "B's implementation of foo" << std::endl;
}
virtual void run() const { // implementation for the Base class
std::cout << "B's implementation of run" << std::endl;
}
virtual void foobar() const { // some other function provided by this class
std::cout << "B's implementation of foobar" << std::endl;
}
};
template<class I, class O, class M>
class C : public A<I,O> {
public:
C() {}
virtual ~C() {}
virtual void bar(M m) const { // some other function provided by this class
std::cout << "C's implementation of bar with: " << m << std::endl;
}
};
Now, what I am trying to do is inherit from both B and C so that I can have the extra methods (foobar, bar), but also not have to implement the method from class A (foo) because it is already defined in B:
template<class I, class O>
class D : public B<I,O>, public C<I,O,int> {
public:
D() {}
void run() const {
this->bar(123);
this->foo();
this->foobar();
}
};
But for some reason the compiler gives me this error:
test.cpp: In function ‘int main(int, char**)’:
test.cpp:68:35: error: cannot allocate an object of abstract type ‘D<float, double>’
A<float, double> *d = new D<float, double>(); // what I need to do
test.cpp:48:11: note: because the following virtual functions are pure within ‘D<float, double>’:
class D : public B<I,O>, public C<I,O,int> {
^
test.cpp:9:22: note: void A<I, O>::foo() const [with I = float; O = double]
virtual void foo() const = 0; // force implementation of this function
This is the code I use to run it:
int main(int argc, char **argv)
{
A<float, double> *b = new B<float, double>();
b->foo(); // prints "B's implementation of foo"
b->run(); // prints "B's implementation of run"
//A<float, double> *c = new C<float, double, int>(); // obviously fails because C does not implement any of A's functions
//A<float, double> *d = new D<float, double>; // line 68: what I need to do
//d->run(); // ***throws the abstract class error
return 0;
}
I want to use the 'run' function of an object of class D from a pointer to a A. As all the functions are virtual I expect to execute implementation of each function defined in the lowest inheritance point, meaning that 'B::run' will be discarded. As 'D::run' uses functions from both B and C I need to inherit from both classes.
I hope I have described it enough and not confused anybody.
Thanks for the help!
If you change B and C to virtually inherit from the A template class, they will share a single base instance when combined by D and this error will go away:
template<class I, class O>
class B : virtual public A<I,O> {
// ...
template<class I, class O, class M>
class C : virtual public A<I,O> {
However, this pattern (known as the diamond inheritance (anti-)pattern) can be very difficult to reason about and I would strongly suggest avoiding it if possible. You are likely to run into even more obscure problems later.
Here is a sample of this technique working, but showing some results that may not be expected at first glance:
class A {
public:
virtual void foo() = 0;
};
class B : virtual public A {
public:
virtual void foo() override;
};
void B::foo()
{
std::cout << "B::foo()" << std::endl;
}
class C : virtual public A { };
class D : public B, public C { };
int main() {
D d;
C & c = d;
c.foo();
return 0;
}
Note that even though you are calling C::foo(), which is pure virtual, since there is only one A instance the inherited pure virtual function resolves to B::foo() though the shared A vtable. This is a somewhat surprising side-effect -- that you can wind up invoking methods implemented on a cousin type.
The answer by #cdhowie gives you a solution.
To understand the problem the compiler is complaining about, take a set of simpler classes:
struct A
{
virtual void foo() = 0;
};
struct B : A
{
virtual void foo() {}
}
struct C : A
{
void bar() {}
}
struct D : B, C
{
};
The class hierarchy of D is:
A A
| |
B C
\ /
D
With this inheritance structure, D has two virtual tables, one corresponding to the B inheritance hierarchy and one corresponding to C inheritance hierarchy. The difference being that in the B hierarchy, there is an implementation of A::foo() while there isn't one in the C hierarchy.
Let's say you were allowed to construct an object of type D.
D d;
C* cp = &d;
Now cp points to the C hierarchy of D, and uses a virtual table in which foo is not implemented. That will be a run time error that the compiler is helping you avoid at compile time.
I know this is a late answer but since you are deriving from a pure virtual function for class C, you have to implement it, then in those functions you call the base class:
virtual void foo() const { // for class C
B::foo();
}
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.