If I have a pure virtual function can it be overriden with a function pointer? Scenario below (I'm aware that it's not 100% syntactically correct):
#include<iostream>
using namespace std;
class A {
public:
virtual void foo() = 0;
};
class B : public A {
public:
B() { foo = &B::caseOne; }
void caseOne() { cout << "Hello One" << endl; }
void caseTwo() { cout << "Hello Two" << endl; }
void (B::*foo)();
void chooseOne() { foo = &B::caseOne; }
void chooseTwo() { foo = &B::caseTwo; }
};
int main() {
B b;
b.(*foo)();
}
EDIT: In case anyone's interested, here's how I accomplished what I wanted to do:
#include<iostream>
using namespace std;
class A {
public:
virtual void foo() = 0;
};
class B : public A {
public:
B() { f = &B::caseOne; }
void caseOne() { cout << "Hello One" << endl; }
void caseTwo() { cout << "Hello Two" << endl; }
void (B::*f)();
void chooseOne() { f = &B::caseOne; }
void chooseTwo() { f = &B::caseTwo; }
void foo() { (this->*f)(); }
};
int main() {
B b;
b.foo();
b.chooseTwo();
b.foo();
}
The output is:
Hello One
Hello Two
No. And you use this wrong. In your code you are trying to assign member-function pointer to function-pointer - it's cannot be compiled.
C++03 standard 10.3/2
If a virtual member function vf is declared in a class Base and in a class Derived, derived directly or
indirectly from Base, a member function vf with the same name and same parameter list as Base::vf is
declared, then Derived::vf is also virtual (whether or not it is so declared) and it overrides
Base::vf.
As #ForEveR said, your code cannot compile. However, since what you actually need is the ability of switching B's implementation of foo in the runtime, we do have workaround:
#include <iostream>
using namespace std;
class A {
public:
virtual void foo() = 0;
};
class B : public A {
private:
void (B::*_f)();
public:
B() { chooseOne(); }
void caseOne() {
cout << "case one" << endl;
}
void caseTwo() {
cout << "case two" << endl;
}
void chooseOne() { _f = &B::caseOne; }
void chooseTwo() { _f = &B::caseTwo; }
void foo() {
(this->*_f)();
}
};
int main(int argc, const char *argv[])
{
A* b = new B();
b->foo();
((B*)b)->chooseTwo();
b->foo();
return 0;
}
UPDATE:
Just found the OP added his answer in the question, which is almost the same as mine. But I think calling foo through pointer instead of instance object is better, for that can exhibit the effect of polymorphism. Besides, it's better to hide f as a private member function.
I think when compile time, the syntax can NOT be compiled. You should provide an override function with the certain name and same args list.
Related
I am facing the following problem with my code:
#include <iostream>
using namespace std;
class Base {
public:
virtual void sayHello()=0;
};
class Impl1 : public Base {
public:
void sayHello() { cout << "Hi from Impl1" << endl; }
};
class Impl2 : public Base {
public:
void sayHello() { cout << "Hi from Impl2" << endl; }
};
void sayHello(Impl1 *i) {
cout << "Impl1 says: ";
i->sayHello();
}
void sayHello(Impl2 *i) {
cout << "Impl2 says: ";
i->sayHello();
}
int main()
{
Impl1 *i1 = new Impl1();
Base *b = i1;
sayHello(b);
return 0;
}
And here the compiler complains about the sayHello(b); line in the
code.
"call of overloaded 'sayHello(Base*&)' is ambiguous"
Is there a way to solve this problem?
EDIT:
I basically want to pass my object to a function that does some calculations based on the type of the object. My object intentionally lacks of information in order to make the needed calculations. So Impl1 and Impl2 just contain some basic data, without the knowledge of more data needed to do the calculations.
Overload resolution is performed at compile time. It means for sayHello(b);, the compiler only know that the type of b is Base*, it won't and can't know that b is pointing to a Impl1 object actually. Then results in ambiguous call; converting Base* to Impl1* or Impl2* is equivalent rank for the call.
PS: might be OT, but for you code sample, a function taking a Base* would work fine; dynamic dispach will take effect.
class Base {
public:
virtual void sayHello()=0;
};
class Impl1 : public Base {
public:
void sayHello() { cout << "Hi from Impl1" << endl; }
};
class Impl2 : public Base {
public:
void sayHello() { cout << "Hi from Impl2" << endl; }
};
void sayHello(Base *i) {
cout << "Some derived class of Base says: ";
i->sayHello();
}
int main()
{
Impl1 i1;
Impl2 i2;
Base *b = &i1;
sayHello(b); // "Hi from Impl1"
b = &i2;
sayHello(b); // "Hi from Impl2"
return 0;
}
If you need to know the dynamic type at run-time, you can use dynamic_cast. e.g.
Base *b = /* something */;
Impl1 * pi1 = dynamic_cast<Impl1*>(b);
if (pi1 != nullptr) sayHello(pi1);
Since overloads are resolved at compile time, you have to supply the compiler with the exact type in order for the overload resolution to succeed.
In order to dispatch on the type, add a virtual member function to the Base, and use it to choose the overload:
class Base {
public:
virtual void sayHello()=0;
virtual void callSayHello() = 0;
};
class Impl1 : public Base {
public:
void sayHello() { cout << "Hi from Impl1" << endl; }
void callSayHello() {sayHello(this); }
};
class Impl2 : public Base {
public:
void sayHello() { cout << "Hi from Impl2" << endl; }
void callSayHello() {sayHello(this); }
};
void sayHello(Impl1 *i) {
cout << "Impl1 says: ";
i->sayHello();
}
void sayHello(Impl2 *i) {
cout << "Impl2 says: ";
i->sayHello();
}
...
b->callSayHello();
Note that implementations of callSayHello are identical, but you cannot place them into Base class, because the type of this would be different.
Note: the idea for this implementation is borrowed from C++ implementation of the Visitor Pattern.
Get rid of the two free-standing functions and call b->sayHello(); directly:
Impl1 *i1 = new Impl1();
Base *b = i1;
b->sayHello();
Or use an ugly workaround with dynamic_cast:
Impl1 *i1 = new Impl1();
Base *b = i1;
sayHello(dynamic_cast<Impl1*>(b));
The need to resort to dynamic_cast often suggests an error in the class design. This may very well be the case here. Chances are that you should never have introduced a supposedly object-oriented base class in the first place.
Note also that you do not call delete at the end. If you do, you will need a virtual destructor in Base.
Is it possible to do such things in C++14. I have a base class as follows:
#include <iostream>
class AbstractElement;
class ConcreteElement;
class SuperConcreteElement;
class B
{
public:
void bar(AbstractElement*)
{
std::cout << "Abstract element" << std::endl;
}
void bar(ConcreteElement*)
{
std::cout << "Concrete element" << std::endl;
}
void bar(SuperConcreteElement*)
{
std::cout << "Super concrete element" << std::endl;
}
};
class AbstractElement
{
public:
virtual void foo() = 0;
};
class ConcreteElement : public AbstractElement
{
private:
B _b;
public:
void foo()
{
_b.bar(this); //1
}
};
class SuperConcreteElement : public AbstractElement
{
private:
B _b;
public:
void foo()
{
_b.bar(this); //2
}
};
int main()
{
AbstractElement *e = new ConcreteElement();
e -> foo(); //Prints Concrete element
}
As you can see at //1 and //2, the function's body is completely similar. But I can't quite move it into a base class because of depending on the static type of this. In spite of that fact, I wouldn't like to write absolutely the same code every time I need to add one more subclass of AbstractElement. So, I need some kind of mechanism which provides us with the facility to inject code into a function.
As long as marcos are not very desirable solution, I'd like to ask about some tricks that can be done in C++14 for solving such a problem.
Yes, it is possible using CRTP:
#include <iostream>
class AbstractElement;
class ConcreteElement;
class SuperConcreteElement;
class B
{
public:
void bar(AbstractElement*)
{
std::cout << "Abstract element" << std::endl;
}
void bar(ConcreteElement*)
{
std::cout << "Concrete element" << std::endl;
}
void bar(SuperConcreteElement*)
{
std::cout << "Super concrete element" << std::endl;
}
};
class AbstractElement
{
public:
virtual void foo() = 0;
};
template <class T>
class CRTPAbstractElement : public AbstractElement
{
B _b;
public:
virtual void foo()
{
T* t = dynamic_cast<T *>(this);
_b.bar(t);
}
};
class ConcreteElement : public CRTPAbstractElement<ConcreteElement>
{
};
class SuperConcreteElement : public CRTPAbstractElement<SuperConcreteElement>
{
};
int main()
{
AbstractElement *e = new ConcreteElement();
e -> foo(); //Prints Concrete element
}
By adding an intermediate CRTP class we are able to cast a pointer to the base class to a pointer to the derived class. Thus solving the issue of code duplication.
I have the following classes:
#include <iostream>
using namespace std;
class M
{
};
class N:public M
{
};
class A
{
public:
virtual void f(M& m)=0;
};
class B:public A
{
public:
void f(M& m){cout<<"using M version"<<endl;}
void f(N& n){cout<<"using N version"<<endl;}
};
and the following implementation:
int main()
{
N n;
A &o = *new B();
o.f(n);
//o.f(static_cast<N&>(n));
}
Basically I want "void f(N&)" to be implemented instead of "void f(M&)" when calling "o.f(n)", but not sure how to achieve it.
For the specific behavior that you describe, you can use a static_cast:
f(static_cast<B&>(*pa));
But everybody is right, you're better off using true polymorphism by making the show() method virtual:
#include <iostream>
using namespace std;
class A
{
private:
int a;
public:
A():a(1){}
virtual void show(){cout<<a<<endl;}
};
class B:public A
{
private:
int b;
public:
B():b(2){}
void show(){cout<<b<<endl;}
};
void f(A & a) {a.show();}
int main()
{
A * pa = new A();
f(*pa);
pa = new B();
f(*pa);
}
You should use virtual functions. This is what polymorphism is for: To determine the type of object at runtime. Modify the code as follows by making f() as a virtual function.
#include <iostream>
using namespace std;
class A
{
private:
int a;
public:
A():a(1){}
void show(){cout<<a<<endl;}
virtual void f(A & a) {a.show();}
};
class B:public A
{
private:
int b;
public:
B():b(2){}
void show(){cout<<b<<endl;}
virtual void f(B & a) {a.show();}
};
int main()
{
A * pa = new A();
f(*pa);
pa = new B();
f(*pa);
}
Keep a pointer to B and call f(*pb). Or f(*static_cast<B*>(pa));.
Although I think what you might really want is to make your method virtual.
virtual void show(){cout<<a<<endl;}
It will still call the first f() but will call the show() method of B.
The following example should help you undertand better the different concepts in actions:
#include <iostream>
using namespace std;
class A
{
public:
void show(){cout<<"show: A"<<endl;}
virtual void show_virtual(){cout << "show_virtual: A" << endl; }
};
class B:public A
{
public:
void show(){cout<<"show: B"<<endl;}
virtual void show_virtual(){cout << "show_virtual: B" << endl; }
};
void f(A & a)
{
cout << "f(A&)" << endl;
a.show();
a.show_virtual();
}
void f(B & b)
{
cout << "f(B&)" << endl;
b.show();
b.show_virtual();
}
int main()
{
A * pa = new A();
B * pb = new B();
A * pb_a = pb;
f(*pa);
cout << endl;
f(*pb);
cout << endl;
f(*pb_a);
}
With the following output
f(A&)
show: A
show_virtual: A
f(B&)
show: B
show_virtual: B
f(A&)
show: A
show_virtual: B
Basically I want "void f(N&)" to be implemented instead of "void
f(M&)" when calling "o.f(n)", but not sure how to achieve it.
You can't call "void f(N&)" because there's no such method in class A.
Solution: Declare void f(N&) in class A:
class A
{
public:
virtual void f(M& m)=0;
virtual void f(N& n)=0;
}
I'm having a very odd problem that I'm hoping someone has come across.
class Letter
{
public:
Letter()
virtual ~Letter()
virtual std::string get() const = 0;
};
class A : public Letter
{
public:
A()
~A()
virtual std::string get() const { return "A"; }
};
class Board
{
public:
Board(){}
~Board()
{
std::cout << "Removing: " << letter->get() << std::endl;
delete letter;
}
void setLetter(Letter * l) { letter = l }
private:
Letter * letter;
}
int main()
{
Board b;
b.setLetter(new A());
}
The program causes a seg fault when Board goes out of scope at the line where the virtual function letter->get() is called in the destructor. I'm using gcc 4.1.2. Any ideas?
UPDATE
Okay, it seems what's actually happening in the real code is the equivalent of this:
class Board
{
public:
Board(){}
~Board()
{
std::cout << "Removing: " << letter->get() << std::endl;
}
void setLetter(Letter * l) { letter = l; }
private:
Letter* letter;
};
int main()
{
Board b;
A a;
b.setLetter(&a);
return 0;
}
In which case A is already out of scope when the virtual function is called.
I can only guess you're attempting to cast the std::string returned from get() to a char*. Otherwise i see no reason for the crash.
#include <iostream>
#include <string>
using namespace std;
class Letter
{
public:
Letter() {}
virtual ~Letter() {}
virtual std::string get() const = 0;
};
class A : public Letter
{
public:
A() {}
~A() {}
virtual std::string get() const { return "A"; }
};
class Board
{
public:
Board(){}
~Board()
{
std::cout << "Removing: " << letter->get() << std::endl;
delete letter;
}
void setLetter(Letter * l) { letter = l; }
private:
Letter * letter;
};
int main()
{
Board b;
b.setLetter(new A());
return 0;
}
no problem in gcc 4.5.2
I didn't realize an object was being passed to setLetter() from the stack, so A was going out of scope before b.
Board b;
A a;
b.setLetter(&a);
Some compilers doesn't allow Plain C / C++ constructors or destructors call virtual methods, seems like the (ANSI) C++ specification neither. And its not recommended.
Sometimes that requirement is useful. Some languages like Object Pascal explicit allow virtual methods calls within constructors and destructors.
One thing you can do its use the "Fake Virtual Constructor Pattern":
class MyClass
{
public:
// constructor
MyClass
{
// anything but virtual methods
}
// destructor
~MyClass
{
// anything but virtual methods
}
virtual void MyFakeConstructor()
{
MyVirtualMethod();
}
virtual void MyFakeDestructor()
{
MyVirtualMethod();
}
virtual void MyVirtualMethod()
{
// more stuff
}
// more members
}
int main(char[][] Args)
{
MyClass MyObject = new MyClass();
MyObject->MyFakeConstructor(); // <-- calls "MyVirtualMethod()"
MyObject->DoSomething1();
MyObject->DoSomething2();
MyObject->DoSomething3();
MyObject->MyFakeDestructor(); // <-- calls "MyVirtualMethod()"
delete MyObject;
return 0;
} // int main()
Another solution its that you arrange your code so you explicit call your virtual method outside the destructor.
Cheers.
Please see the example code below:
class A
{
private:
class B
{
public:
foobar();
};
public:
foo();
bar();
};
Within class A & B implementation:
A::foo()
{
//do something
}
A::bar()
{
//some code
foo();
//more code
}
A::B::foobar()
{
//some code
foo(); //<<compiler doesn't like this
}
The compiler flags the call to foo() within the method foobar(). Earlier, I had foo() as private member function of class A but changed to public assuming that B's function can't see it. Of course, it didn't help. I am trying to re-use the functionality provided by A's method. Why doesn't the compiler allow this function call? As I see it, they are part of same enclosing class (A). I thought the accessibility issue for nested class meebers for enclosing class in C++ standards was resolved.
How can I achieve what I am trying to do without re-writing the same method (foo()) for B, which keeping B nested within A?
I am using VC++ compiler ver-9 (Visual Studio 2008). Thank you for your help.
foo() is a non-static member function of A and you are trying to call it without an instance.
The nested class B is a seperate class that only has some access privileges and doesn't have any special knowledge about existing instances of A.
If B needs access to an A you have to give it a reference to it, e.g.:
class A {
class B {
A& parent_;
public:
B(A& parent) : parent_(parent) {}
void foobar() { parent_.foo(); }
};
B b_;
public:
A() : b_(*this) {}
};
This is an automagic, albeit possibly nonportable trick (worked on VC++ since 6.0 though). Class B has to be a member of class A for this to work.
#ifndef OUTERCLASS
#define OUTERCLASS(className, memberName) \
reinterpret_cast<className*>(reinterpret_cast<unsigned char*>(this) - offsetof(className, memberName))
#endif
class A
{
private:
class B
{
public:
void foobar() {
A* pA = OUTERCLASS(A, m_classB);
pA->foo();
}
} m_classB;
public:
foo();
bar();
};
Basically what Georg Fritzsche said
#include <iostream>
#include <cstring>
using namespace std;
class A
{
private:
class B
{
A& parent_;
public:
//B(); //uncommenting gives error
~B();
B(A& parent) : parent_(parent) {}
void foobar()
{
parent_.foo();
cout << "A::B::foo()" <<endl;
}
const std::string& foobarstring(const std::string& test) const
{
parent_.foostring(test); cout << "A::B::foostring()" <<endl;
}
};
public:
void foo();
void bar();
const std::string& foostring(const std::string& test) const;
A();
~A(){};
B b_;
};
//A::B::B() {}; //uncommenting gives error
A::B::~B(){};
A::A():b_(*this) {}
void A::foo()
{
cout << "A::foo()" <<endl;
}
const std::string& A::foostring(const std::string& test) const
{
cout << test <<endl;
return test;
}
void A::bar()
{
//some code
cout << "A::bar()" <<endl;
foo();
//more code
}
int main(int argc, char* argv[])
{
A a;
a.b_.foobar();
a.b_.foobarstring("hello");
return 0;
}
If you uncomment the default B constructor you would get an error
If you want to reuse functionality from A then you should inherit from A not nest B inside it.
Combining Igor Zevaka's and enthusiasticgeek's answers. Also, using reinterpret_cast for calculating offset (If you create class member variable using new keyword):
#include <iostream>
#include <cstring>
using namespace std;
template < typename T, typename U > constexpr size_t offsetOf(U T:: *member)
{
return (char*) &((T*) nullptr->*member) - (char*) nullptr;
}
class A
{
private:
class B
{
public:
B(string message);
~B();
void foobar()
{
A *pA = reinterpret_cast<A*> (reinterpret_cast< unsigned char*> (this) - offsetOf(&A::b_));
pA->foo();
pA->bar();
std::cout << "DONE!";
}
};
public:
void foo();
void bar();
A();
~A() {};
B* b_ = new B("Hello World!");
};
A::A()
{
cout << "A constructor\n";
};
A::B::B(string message) {
cout << "B constructor\n";
cout << "Message = " << message << "\n";
};
A::B::~B() {};
void A::foo()
{
cout << "A::foo()" << endl;
}
void A::bar()
{
cout << "A::bar()" << endl;
foo();
}
int main(int argc, char *argv[])
{
A* a = new A();
a->b_->foobar();
return 0;
}
Output:
B constructor
Message = Hello World!
A constructor
A::foo()
A::bar()
A::foo()
DONE!
References:
https://stackoverflow.com/a/10607424/9524565
https://stackoverflow.com/a/3058382/9524565
https://stackoverflow.com/a/20141143/9524565