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
Related
So I have a vector of base classes and a couple bugs in my code, which means that I need to know which derived class is calling the polymorphic method:
class Base {
virtual void render() {}
}
class Derived1 {
void render() override {/*do stuff*/}
}
class Derived2 {
void render() override {/*do stuff*/}
}
class Game {
std::vector<Base> baseVec;
void render() {
for(Base b: baseVec) {
b.render();
//std::cout << typeid(b).name() << std::endl; prints base class' name, and requires some logic to unmangle the actual name
//std::cout << std::type_index(typeid(b)).name() << std::endl; also prints base class' name
//std::cout << typeNames[std::type_index(typeid(b))] << std::endl; typeNames is an unordered_map<std::type_index, std::string> - still prints the base class' name, and the list has to be punched in by hand (bad)
}
}
}
Below code is modified for your requirement as per my understanding for your requirements:
class Base {
public:
virtual void render() = 0;
};
class Derived1: public Base {
void render() override { std::cout << "Derived1"<<std::endl; }
};
class Derived2: public Base {
void render() override { std::cout << "Derived2" << std::endl; }
};
int main()
{
std::vector<Base*> baseVec;
Derived1 d;
Derived2 d1;
baseVec.push_back(&d);
baseVec.push_back(&d1);
for (auto& b : baseVec)
{
b->render();
std::cout << typeid(*b).name() << std::endl;
}
return 0;
}
Output:
Derived1
class Derived1
Derived2
class Derived2
The typeid is solving your name by using=> typeid(*b).name().
typeid explained
I'm a newbie in C++ and have a question. I can't find any related stuff for this question on Google.
Is it possible in C++ for code in a virtual function to be called from the base class without invoking it with Base::func() in the derived class?
Here is an example of what I mean:
class Base {
public:
virtual void func(void) { cout << "Base func()" << endl; }
};
class Derived : Base {
public:
virtual void func(void) { cout << "Derived func()" << endl; }
};
The output should be the following when the function func is called from Derived:
Base func()
Derived func()
Is this even possible in C++? Or, is there another way to implement this behavior?
Is that intention even possible in C++? Or is there a other way to implement this behavior in C++?
You can get that behavior only if you add
Base::func();
in the implementation of Derived::func(). The language does not provide a mechanism to make that automatic.
You can make the base class get the calls first by making the interface non-virtual, and then call the (private) derived function from there:
class Base {
public:
void func()
{
cout << "Base func()" << endl;
derived_func();
}
private:
virtual void derived_func() { }
};
class Derived : Base {
private:
virtual void derived_func() { cout << "Derived func()" << endl; }
};
You have call the base class in derived class implementation to make that happen
class Base {
public:
virtual void func(void) { cout << "Base func()" << endl; }
};
class Derived : Base {
public:
virtual void func(void)
{
Base::function();
cout << "Derived func()" << endl;
}
};
But this is still calling Base::func() from Derived::func()
You can, however, achieve what you want if the func() was actually your constructor.
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
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()
I have a problem that I have not yet tested/compiled and wondering if it is possible and if it is bad design?
My Problem:
I want to have an abstract base class A and a abstract derived class B.
I realize if this is possible I will have a number of pure virtual member functions in each class and also I will not be able to initialize these objects, but that is a given for abstract classes.
In my design I will have another derived class C which I would then initialize - class C would be derived from class B.
I would have something that looked like this
class C
^
|
abstract class B
^
|
abstract base class A
My Question:
Is this possible first of all? I would suspect so, but not declaring the pure virtual functions in A in class B may be troublesome?
e.x.
class A {
public:
virtual void test()=0;
};
class B: public A {
public:
virtual void test()=0;
virtual void anotherTest()=0;
};
Is the above okay?
Is this bad c++ design? In future I will have derived classes from A so it would be nice to have this design.
Nothing wrong with it, and it will certainly work. Example follows
stefanos-imac:dftb borini$ more test.cpp
#include <iostream>
class A {
public:
A(void) { std::cout << "A" << std::endl; }
virtual void method1() = 0;
};
class B : public A {
public:
B(void) : A() { std::cout << "B" << std::endl; }
virtual void method2() = 0;
};
class C : public B {
public:
C(void) : B() { std::cout << "C" << std::endl; }
virtual void method1() { std::cout << "method1" << std::endl; }
virtual void method2() {std::cout << "method2" << std::endl; }
};
int main() {
C c;
c.method1();
c.method2();
}
stefanos-imac:dftb borini$ ./a.out
A
B
C
method1
method2
Thank you for reminding me that I can still type basic C++.