I have some code I'm trying to get to work, I'm open to other suggestions on how to do this. Basically, I have some base class that I want a bunch of subclasses to inherit. I then have a function that needs to call the subclass version of this method.
#include <iostream>
using namespace std;
//my base class
class BaseClass {
public:
void myMethod(){
std::cout << "Base class?" << std::endl;
}
};
/my subclass
class SubClass1: public BaseClass{
public:
void myMethod(){
std::cout << "Subclass?" << std::endl;
}
};
//method that I want to call SubClass.myMethod(). I cannot declare this as
//SubClass1 because there will be multiple of these.
void call_method(BaseClass object){
return object.myMethod();
}
int main()
{
BaseClass bc;
SubClass1 sb1;
//works how I expect it to
sb1.myMethod();
//I want this to also print "Subclass?"
//but it prints "Base class?".
call_method(sb1);
return 0;
}
Thanks for your help
You need to declare the member function in the base class as virtual. For example
virtual void myMethod() const {
std::cout << "Base class?" << std::endl;
}
And in the derived class to override it
void myMethod() const override {
std::cout << "Subclass?" << std::endl;
}
And the function call_method must have a parameter that represents a reference to base class object
void call_method( const BaseClass &object){
object.myMethod();
}
Related
I have the following test code. Here, the output is "from parent", how can I call the child function? Why is the child function not getting called? is is recommended to inherit from a singleton?
#include <iostream>
using namespace std;
class Singleton
{
public:
static Singleton& getInstance()
{
static Singleton s;
return s;
}
virtual void func()
{
cout << "from parent" << endl;
}
};
class Child : public Singleton
{
public:
void func() override
{
cout << "from child" << endl;
}
};
int main()
{
Singleton& s = Child::getInstance();
s.func();
}
Right now, Singleton::getInstance always returns a Singleton. Child doesn't have its own version of getInstance, so Child::getInstance() resolves to a call to Singleton::getInstance() which returns a Singleton, not a Child. If we use the CRTP, we can make it so Singleton::getInstance actually knows the derived type we're trying to get an instance of:
#include <iostream>
#include <type_traits>
template <class Derived>
class Singleton
{
public:
static Derived& getInstance()
{
// Assert that the template arg really is derived from the appropriate instantiation of the base class template
static_assert(std::is_base_of<Singleton<Derived>, Derived>::value);
static Derived s;
return s;
}
virtual void func()
{
std::cout << "from parent" << std::endl;
}
};
class Child : public Singleton<Child>
{
public:
void func() override
{
std::cout << "from child" << std::endl;
}
};
int main()
{
auto& s = Child::getInstance(); // s is a Child here
s.func(); // Outputs "from child" as expected
}
I'm trying to solve an inheritance problem, where a derived class Snake inherits from LivingThing -> Animal -> Reptile, however, when I don't add virtual void crawl() to class LivingThing, the compiler says error: no member named 'crawl' in 'LivingThing'. Now I don't want to have to implement a virtual void in LivingThing which is specific for Snakes.
#include <iostream>
class LivingThing
{
public:
void breathe()
{
std::cout << "I'm breathing as a living thing." << std::endl;
}
virtual void crawl() {} //dont' want this
};
class Animal : virtual public LivingThing
{
public:
void breathe()
{
std::cout << "I'm breathing as an animal." << std::endl;
}
};
class Reptile : virtual public LivingThing
{
public:
void crawl()
{
std::cout << "I'm crawling as a reptile." << std::endl;
}
void breathe()
{
std::cout << "I'm breathing as a reptile." << std::endl;
}
};
class Snake : public Animal, public Reptile
{
public:
void breathe()
{
std::cout << "I'm breathing as a snake." << std::endl;
}
void crawl()
{
std::cout << "I'm crawling as a snake." << std::endl;
}
};
int main()
{
LivingThing *snake = new Snake();
snake->breathe();
snake->crawl();
system("pause");
return 0;
}
snake->crawl(); tries to access crawl through a LivingThing*, without a v-table reference, LivingThing* cannot call Snake::crawl.
In your current example you could just change the LivingThing pointer to be a Snake pointer.
In a more complex situation:
If you know that the pointer you're calling crawl on points to an object that is infact a Snake then you can static_cast the pointer.
if(Snake* snake = static_cast<Snake*>(livingThing))
snake->crawl();
If you have no guarantee that the living thing is actually a Snake and you have rtti available then you can use dynamic_cast.
if(Snake* snake = dynamic_cast<Snake*>(livingThing))
snake->crawl();
When you upcast object to it's base type, you can only use methods which are declared in this base class. So if you don't want to declare crawl method in your base type, you've to downcast your object before using this method:
LivingThing *creature = new Snake();
creature->breathe();
if(Snake* snake = dynamic_cast<Snake*>(creature)) snake->crawl();
I am expecting "My Game" to print out but I am getting "Base"
This only happens when using methods internally inside the class.
#include <iostream>
namespace Monster { class App {
public:
App(){}
~App(){}
void run(){
this->speak();
}
void speak(){
std::cout << "Base" << "\n";
};
};}; // class / namespace
class MyGame : public Monster::App {
public:
MyGame(){}
~MyGame(){}
void speak(){
std::cout << "My Game" << "\n";
};
};
int main(){
MyGame *child = new MyGame;
child->run();
return 0;
}
In C++ you need to specifically declare a function to be virtual:
class BaseClass {
virtual void speak () {
...
}
};
In C++ a method can only be overridden if it was marked virtual. You can think of virtual as a synonym for "overridable".
The virtual keyword has to appear in the base class. It may also appear optionally in the subclasses at the point of override, but it does not have to.
If you are using a compiler that supports C++11 (and you should if you are learning C++), I recommend that you always use the new override keyword when you mean to override:
class Base {
public:
virtual void speak() {
std::cout << "Base";
}
};
class Derived : public Base {
public:
void speak() override { // <---
std::cout << "Derived";
}
};
If the method isn't actually an override, the compiler will tell you so by giving an error.
It is not always obvious on the first read whether a method is an override. For example the following is correct thanks to return type covariance:
class A {};
class B : public A {};
class Base {
public:
virtual A* foo() {
return nullptr;
}
};
class Derived : public Base {
public:
B* foo() override {
return nullptr;
}
};
This might not be useful very often, but override makes it clear in case someone has to read it.
Also, if you have at least one virtual method in your class, also make its destructor virtual. This will assure that all the destructors will run when needed and things get cleaned up properly:
class App {
public:
App() {}
virtual ~App() {} // <---
void run() {
this->speak();
}
virtual void speak() {
std::cout << "Base\n";
};
};
I have the following two classes. Since Child inherits from Father, I think that Child::init() overrides Father::init(). Why, when I run the program, I get "I'm the Father" and not "I'm the Child"? How to execute Child::init()?
You can test it here: https://ideone.com/6jFCRm
#include <iostream>
using namespace std;
class Father {
public:
void start () {
this->init();
};
void init () {
cout << "I'm the father" << endl;
};
};
class Child: public Father {
void init () {
cout << "I'm the child" << endl;
};
};
int main (int argc, char** argv) {
Child child;
child.start();
}
Currently Child::init is hiding Father::init, not overriding it. Your init member function needs to be virtual in order to get dynamic dispatch:
virtual void init () {
cout << "I'm the father" << endl;
};
Optionally, you could mark Child::init as override to be explicit that you want to override a virtual function (requires C++11):
void init () override {
cout << "I'm the child" << endl;
};
You should define the function with function specifier virtual
For example
#include <iostream>
using namespace std;
class Father {
public:
virtual ~Father() {}
void start () {
this->init();
};
virtual void init () const {
cout << "I'm the father" << endl;
};
};
class Child: public Father {
void init () const override {
cout << "I'm the child" << endl;
};
};
int main()
{
Child child;
child.start();
return 0;
}
Otherwise function start searches name init in the scope of its own class. And because function init is not virtual that is it is not overriden in the derived class the base class function init is called.
If you want the child to override the init method, you must make the init method in the base class virtual.
class Father {
public:
void start () {
this->init();
};
virtual void init () {
cout << "I'm the father" << endl;
};
};
A class that re-declares and re-implements a virtual method of one of its bases, is said to override that method. In order for late binding to occur for a method, you need to declare that method virtual.
I am expecting "My Game" to print out but I am getting "Base"
This only happens when using methods internally inside the class.
#include <iostream>
namespace Monster { class App {
public:
App(){}
~App(){}
void run(){
this->speak();
}
void speak(){
std::cout << "Base" << "\n";
};
};}; // class / namespace
class MyGame : public Monster::App {
public:
MyGame(){}
~MyGame(){}
void speak(){
std::cout << "My Game" << "\n";
};
};
int main(){
MyGame *child = new MyGame;
child->run();
return 0;
}
In C++ you need to specifically declare a function to be virtual:
class BaseClass {
virtual void speak () {
...
}
};
In C++ a method can only be overridden if it was marked virtual. You can think of virtual as a synonym for "overridable".
The virtual keyword has to appear in the base class. It may also appear optionally in the subclasses at the point of override, but it does not have to.
If you are using a compiler that supports C++11 (and you should if you are learning C++), I recommend that you always use the new override keyword when you mean to override:
class Base {
public:
virtual void speak() {
std::cout << "Base";
}
};
class Derived : public Base {
public:
void speak() override { // <---
std::cout << "Derived";
}
};
If the method isn't actually an override, the compiler will tell you so by giving an error.
It is not always obvious on the first read whether a method is an override. For example the following is correct thanks to return type covariance:
class A {};
class B : public A {};
class Base {
public:
virtual A* foo() {
return nullptr;
}
};
class Derived : public Base {
public:
B* foo() override {
return nullptr;
}
};
This might not be useful very often, but override makes it clear in case someone has to read it.
Also, if you have at least one virtual method in your class, also make its destructor virtual. This will assure that all the destructors will run when needed and things get cleaned up properly:
class App {
public:
App() {}
virtual ~App() {} // <---
void run() {
this->speak();
}
virtual void speak() {
std::cout << "Base\n";
};
};