C++ - Base class pointer, method pointer, refer to derived class, method? - c++

class Base
{
virtual void Foo(){}
virtual void Bar(){}
};
class Derived1 : public Base
{
void Foo(){ //Do something }
void Bar(){ //Do something }
}
class Derived2 : public Base
{
void Foo(){ //Do something }
void Bar(){ //Do something }
}
class OtherClass
{
public:
Base* obj;
void (Base::*method)();
void Add( Base* _obj, void (Base::*_method)() )
{
obj = _obj;
method = _method;
}
void Run()
{
( obj->method )();
}
}
int main()
{
Derived1 d1;
Derived2 d2;
OtherClass other;
other.Add( &d1, &(Derived1::Foo) );
//other.Add( &d2, &(Derived2::Bar) ); etc, etc.
other.Run();
}
My question:
Say I have a derived class with a method, I can refer to an instance of that class with a pointer of it's base type. Assuming I know what method I want to call, I can then call it via that pointer and the derived class's method will be called.
How can I achieve similar polymorphic behaviour when I specify the method to be called by supplying a method pointer?
The real code the above is based on will compile if I cast the method pointer, but it appears to not be doing any-- It is at this point I've realised I wasn't calling OtherClass's update method, which is why I wasn't getting any joy. :D So this works, as is (almost). Stupid, stupid brain.
Slight course correction then: Right now I need to static cast the method pointer I pass to OtherClass, to a pointer to Base class method when I pass it to Add. This is not ideal.
Can I get the same behaviour if I pass &(Base::Foo), for example, to the method Add?
Will Derived1::Foo be called if I invoke that method on a pointer to base type that refers to an instance of the derived type?
I get the feeling it'll call the base member. :(
Some reading:
Is it safe to "upcast" a method pointer and use it with base class pointer?
C++ inheritance and member function pointers
Pointer to member conversion
Casting a pointer to a method of a derived class to a pointer to a method of a base class

i believe you're pondering whether a member-fn-ptr of a virtual base will fire the polymorphic derivation override if provided in a derived class. If so, the answer is yes, and the code below demonstrate this.
Hope this helps.
#include <iostream>
class Base
{
public:
virtual void Foo()
{
std::cout << __PRETTY_FUNCTION__ << '\n';
}
virtual void Bar()
{
std::cout << __PRETTY_FUNCTION__ << '\n';
}
};
class Derived1 : public Base
{
public:
void Foo()
{
std::cout << __PRETTY_FUNCTION__ << '\n';
}
void Bar()
{
std::cout << __PRETTY_FUNCTION__ << '\n';
}
};
class Derived2 : public Base
{
public:
void Foo()
{
std::cout << __PRETTY_FUNCTION__ << '\n';
}
void Bar()
{
std::cout << __PRETTY_FUNCTION__ << '\n';
}
};
class OtherClass
{
public:
Base* obj;
void (Base::*method)();
void Add( Base* _obj, void (Base::*_method)() )
{
obj = _obj;
method = _method;
}
void Run()
{
(obj->*method)();
}
};
int main()
{
Derived1 d1;
Derived2 d2;
OtherClass other;
other.Add( &d1, &Base::Foo );
other.Run();
other.Add( &d2, &Base::Bar);
other.Run();
}
Output
virtual void Derived1::Foo()
virtual void Derived2::Bar()

Related

C++ interface inheritance different arguments method

class Base
{
public:
virtual void print() = 0;
};
class A : public Base
{
int mClassA;
public:
A() : mClassA(1) {}
void print() override { std::cout << "print A" << std::endl; }
void foo( A& arg ) { std::cout << mClassA << std::endl; }
};
class B : public Base
{
int mClassB;
public:
B() : mClassB(2) {}
void print() override { std::cout << "print B" << std::endl; }
void foo( B& arg ) { std::cout << mClassB << std::endl; }
};
So I got class structure similar to this. What approach should I take to call foo without dynamic_cast each time?
int main()
{
Base * obj1 = new A();
Base * obj2 = new A();
dynamic_cast<A*>(obj1)->foo(*dynamic_cast<A*>(obj2));
}
I could create foo method with base class argument but I want to be sure that I'm passing A or B obejct as an argument.
You could use templates to make sure that a particular parameter of one of the class' member functions has at least a particular type. See the following code illustrating this:
template <class P>
class Base
{
public:
Base(int nr) : mClass(nr) {}
virtual void print() = 0;
virtual void foo( P& arg ) { std::cout << mClass << std::endl; }
protected:
int mClass;
};
class A : public Base<A>
{
public:
A() : Base(1) {}
void print() override { std::cout << "print A" << std::endl; }
virtual void foo( A& arg ) override { Base::foo(arg); cout << "is A for sure" << endl; }
};
class B : public Base<B>
{
public:
B() : Base(2) {}
void print() override { std::cout << "print A" << std::endl; }
virtual void foo( B& arg ) override { Base::foo(arg); cout << "is B for sure" << endl; }
};
int main()
{
Base<A> * obj1 = new A();
A* obj2 = new A();
obj1->foo(*obj2);
Base<B> * objb1 = new B();
B* objb2 = new B();
objb1->foo(*objb2);
// objb1->foo(*obj2);
// Non-const lvalue reference to type 'B' cannot bind to a value of unrelated type 'A'
}
It sounds like you're wanting to do something like this:
class Base
{
public:
virtual void foo(Base&) = 0;
};
class A : public Base
{
public:
void foo(A&);
};
class B : public Base
{
public:
void foo(B&);
};
In object oriented design, this is known as covariance (specifically, a "covariant method argument type").
The problem is that this goes against principles of good object oriented design. The Liskov substitution principle says that, if you have a base class Base, then any instances of subclasses of Base need to be interchangeable - but you want some subclasses of Base to not work with other subclasses of Base. (This is an oversimplification, but there are plenty of discussions online with more detail.)
If you want to do this - if it's the best solution in your case, in spite of the general advice of the Liskov substitution principle - then you can implement the checks yourself.
void A::foo(Base& base_arg) {
// This will throw a runtime exception if the wrong type
A& arg = dynamic_cast<A&>(base_arg);
std::cout << mClassA << std::endl;
}
Note that you're sacrificing some compile-time type safety now - if you accidentally try to call A::foo with an instance of B, you won't know until the code runs and you get an exception. (That's the whole point of virtual functions / dynamic dispatch / polymorphism - the behavior is determined at runtime.)
Another approach would be to use templates, like #Stephen Lechner's solution. That gives up runtime polymorphism, but it keeps strong type safety and better follows conventional OO design.
The Wikipedia article on covariance has a lot more discussion, including further example code.

C++ inheritance and virtual functions

Reading through a text book, I have come away with the impression that overriding virtual functions only works when using a pointer or reference to the object. The book demonstrates the creation of a pointer of the base class type pointed to an object the derived class type, and uses that to demonstrate a virtual function override.
However, I've now come across the following. Not a pointer in sight, and I was expecting that making function1 virtual would not make a difference, but it does. I'm clearly missing something here and would appreciate an explanation as to what it is. Sorry if my explanation isn't clear; also I expect this has been asked before, but was unable to come up with what to search on.
using namespace std;
class ClassA
{
public:
void function1(); // virtual or not?
void function2();
};
class ClassB : public ClassA
{
public:
void function1();
};
int main()
{
ClassA objA;
ClassB objB;
objA.function1();
cout << "\n";
objA.function2();
cout << "\n";
objB.function1();
cout << "\n";
objB.function2(); // Fourth call
cout << "\n";
}
void ClassA::function1() { cout << "ClassA::function1\n"; }
void ClassA::function2()
{
cout << "ClassA::function2\n";
function1(); // For the fourth call ClassA::function1()
// is called if ClassA::function1() is not virtual
// but ClassB:function1() is called if it is. Why?
}
void ClassB::function1() { cout << "ClassB::function1\n"; }
Many thanks for any help.
It's not a virtual function as it is not marked as one. It's simply a public function accessible from a derived class / object. Your code is not exhibiting polymorphic behavior either. That being said none of your functions are virtual nor overriding. Trivial example for polymorphic installation would be:
#include <iostream>
#include <memory>
class ClassA {
public:
virtual void function1() { // now virtual
std::cout << "ClassA::function1\n";
}
};
class ClassB : public ClassA {
public:
void function1() override {
std::cout << "ClassB::function1\n";
}
};
int main() {
std::unique_ptr<ClassA> p = std::make_unique<ClassB>();
p->function1(); // now calls class B function, overrides class A behavior
}
or through references:
int main() {
ClassB objB;
ClassA& ro = objB;
ro.function1(); // now calls class B function, overrides class A behavior
}
There is little benefit in marking functions as virtual and override if you are not utilizing polymorphic behaviour.
Example of virtual without explicit pointers :
class A
{
public:
virtual void f1()
{
cout << "A::f1()" << endl;
}
void f2()
{
f1();
}
};
class B : public A
{
public:
void f1() override
{
cout << "B::f1()" << endl;
}
};
int main()
{
A a;
B b;
a.f2();
b.f2();
}
function1 is not virtual, obj2 calls the classB function1 because it is a clasB object, the compiler first looks at the most-derived type for a function, then the leftmost base (and on through the bases of that base), and then the next base in multiple inheritance situations. If you took a classA * to obj2 and called function1 it would call the classA function1.

Call virtual function after derived class object construction

Here is some sample code:
#include <iostream>
class A {
public:
virtual void foo() {
std::cout << "base" << std::endl;
}
A() {
foo();
}
};
class B : public A {
int a;
public:
void foo() {
std::cout << "derived" << std::endl;
}
B(int a) :
a(a) {}
};
int main() {
B o(1);
return 0;
}
I want foo() to get called every time some A derived object is constructed. I do not want to call foo() explicitly in every derived class constructor.
Is there a way to do this in some elegant way?
There is no way you can call an overridden foo() from a base class constructor, no matter what you do. When the base class constructor is called, the derived class object has not been constructed yet, so you cannot call any of its methods or access any of its members. This is true for virtual functions and regular functions as well. In a base class constructor, the this pointer is pointing at the base class, not the derived class.
A potential workaround is to delegate construction to a separate function that clients will have to call instead. Then have that function call foo after construction:
class A {
public:
virtual void foo() {
std::cout << "base" << std::endl;
}
template<typename T, typename ... Args>
static T construct(Args ... args)
{
T newT{ args... };
newT.foo();
return std::move(newT);
}
protected:
A() {
//Construct A
}
};
class B : public A {
int a;
public:
void foo() {
std::cout << "derived" << std::endl;
}
B(int a) :
a(a) {}
};
int main()
{
B o = A::construct<B>(1);
A a = A::construct<A>();
return 0;
}

Force sub-classes to implement and call (once) a method

I am looking for a way to create a method that has to be implemented by every subclass. I also want the subclass to call this method on construction.
It should not be possible to call this method again after class construction..
#include <iostream>
class Base {
public:
Base() {init();}
private:
virtual void init() = 0;
};
class DerivedA : public Base {
public:
DerivedA() {}
private:
virtual void init() { std::cout << "Hello, I am A.";}
};
class DerivedB : public Base{
public:
DerivedB() {}
private:
virtual void init() {std::cout << "Hello, I am B.";}
};
int main(){
DerivedA a;
DerivedB b;
return 0;
}
This is an example, but it is not valid, because it calls a pure virtual method in constructor. Of course I can add init() in every subclass-constructor, but then it can be forgotten on new subclasses.
What is the C++ way of doing this?
The C++ way is to not do this. Init functions are bad. Simply use the constructors.
AFAIK, it is very dangerous to call virtual functions in constructors. Here is a simple example. I slightly modified your code to have init method also implemented in Base class :
#include <iostream>
#include <exception>
class Base {
protected:
Base() {init() ; }
virtual void init() {
std::cout << "Init base" << std::endl;
}
public:
void callinit() {
init();
}
};
class DerivedA : public Base {
public:
DerivedA() {}
protected:
virtual void init() { std::cout << "Hello, I am A."<< std::endl;}
};
class DerivedB : public Base{
public:
DerivedB() {}
protected:
virtual void init() {std::cout << "Hello, I am B."<< std::endl;}
};
int main(){
DerivedA a;
DerivedB b;
a.callinit();
b.callinit();
return 0;
}
and the output is :
Init base
Init base
Hello, I am A.
Hello, I am B.
What can we conclude of that :
once the object is constructed, all is fine and when we call init method we normaly get the correct implementation from derived class
but in constructor, the order is :
call Base constructor
call init method from Base object (since derived object in not still constructed)
call DerivedX constructor
So the method is always the one from Base which is definitively not what you expected.
As the other poster said, you should probably stay away from this, but the easiest example would be to make a public, non-virtual interface method on Base called Init() that must be called after the object is constructed. That method can call a pure-virtual "DoInit" method on the derived classes, and track whether or not it has been called yet with an internal flag.
I don't recommend this, but it will work.
class Base
{
public:
void Init()
{
if(!initialized)
{
DoInit();
initialized = true;
}
}
protected:
virtual void DoInit() = 0; // derived classes need to implement this
private:
bool initialized {false};
};
I faced similar problem and could not find a simple solution. I had to make the initialization in a separate class. An object of this class can be passed to Base/Derive constructors, or this class can be a template parameter.
class Initializer {
. . .
}
class Base {
public:
Base(Initializer* initializer) {
// Get members from initializer
}
}
Or:
template<Initializer TInitializer>
class Base<TInitializer> {
public:
Base() {
TInitializer initializer;
// Get members from initializer
}
}
Sorry, I did not write in C++ too long, so I could prevent some syntax errors.
C++11's call_once gets you most of the way, but it has costs.
The class will not be movable nor copyable.
You must add an extra line in every function that requires the initialization.
It does not prevent the method from being called more than once, but that is easy to add.
#include <iostream>
#include <mutex>
struct Base {
Base() {
std::cout << "Base ctor" << std::endl;
}
void sampleFunction1() {
// this line must be at the start of every function that needs the initialization
std::call_once(initedFlag, &Base::v_init, this);
std::cout << "Base::sampleFunction1" << std::endl;
}
void sampleFunction2() {
// this line must be at the start of every function that needs the initialization
std::call_once(initedFlag, &Base::v_init, this);
std::cout << "Base::sampleFunction2" << std::endl;
}
private:
virtual void v_init() = 0;
std::once_flag initedFlag;
};
Notice that the Derived class has nothing special, except that it provides v_init.
struct Derived : Base {
Derived() {
std::cout << "Derived ctor" << std::endl;
}
private:
void v_init() override {
std::cout << "Derived::v_init" << std::endl;
}
};
Demo code
int main(int argc, const char * argv[]) {
Derived d1;
Derived d2;
std::cout << "Calling d1" << std::endl;
d1.sampleFunction1();
d1.sampleFunction2();
std::cout << "Calling d2" << std::endl;
d2.sampleFunction2();
d2.sampleFunction1();
return 0;
}
Output: Notice that v_init will be called which ever sample function is called first and is not called in the ctors.
Base ctor
Derived ctor
Base ctor
Derived ctor
Calling d1
Derived::v_init
Base::sampleFunction1
Base::sampleFunction2
Calling d2
Derived::v_init
Base::sampleFunction2
Base::sampleFunction1

Passing derrived classes as virtual base class without loss of changes

I have 1 base class and a couple of derrived classes that are pretty identic to the base. They look kind of like that:
class Base
{
protected:
data stuff;
size_t length;
public:
Base();
~Base();
virtual void print()
{
std::cout << "Base" << std::endl;
}
// Some more virtual functions
};
class Der1: public Base
{
public:
void print()
{
std::cout << "Der1" << std::endl;
Base::print();
}
};
class Der2: public Base
{
public:
void print()
{
std::cout << "Der2" << std::endl;
Base::print();
}
};
This example is kind of stupid, but what I want to say is that derived classes don't really affect the data itself - only 1 method that does something before actually printing data.
The problem I have is that I have some functions that get Base class as a parameter and does something with the data. The problem is - I can pass derived classes to those functions, but they are passes as Base class - so they lose their overloaded print, and if printed from inside of such function - it won't print any "Der1" or "Der2" strings to stdout.
Edit: They are passed as (const Base &source)
So my question is - what is a way to properly pass derived classes to such functions?
It looks like your functions get Base class as the parameter by value. If you use passing by reference instead - so function(Base& object) instead of function(Base object) - nothing will be lost.
In addition to previous answer, please see below your example:
#include <iostream>
class Base
{protected:
int stuff;
size_t length;
public:
Base(){};
~Base(){};
virtual void print()
{std::cout << "Base" << std::endl;}
// Some more virtual functions
};
class Der1: public Base
{public:
Der1(){};
~Der1(){};
void print()
{
std::cout << "Der1" << std::endl;
Base::print();
};
};
class Der2: public Base
{public:
void print()
{
std::cout << "Der2" << std::endl;
Base::print();
};
};
void function(Base& base)
{
base.print();
}
int main(void)
{
Der1 derived;
function(derived);
return 0;
}
Execution:
Der1
Base