I have written a small application using dynamic_cast to determine whether it is form the base class or the child class and invokes the function according to it. But when ever child class
runs, it displays it function twice and no sure why it does that.
#include <iostream>
using namespace std;
class Base{
public:
virtual void setting(){
cout << "Hello, I am a function from the base class" << endl;
}
virtual void say(){
cout << "Base class says hi" << endl;
}
};
class Child:public Base{
public:
void setting(){
cout << "Hello, I am a function from the child class" << endl;
}
void say(){
cout << "Child class says hi" << endl;
}
};
void Ready(Base* input){
Base* bp = dynamic_cast<Base*>(input);
if(bp){
bp->setting();
bp->say();
}
Child* cp = dynamic_cast<Child*>(input);
if(cp){
cp->say();
cp->setting();
}
}
int main(){
Base b;
Child c;
Ready(&b);
cout << endl;
Ready(&c); //runs twice for some reason
system("pause");
return 0;
}
When you pass a pointer to Child to the Ready function, both dynamic_casts succeed. Child is both a Base and a Child.
Here's a simplified example:
struct Foo
{
virtual ~Foo() {}
};
struct Bar : Foo {};
#include <iostream>
int main()
{
Bar b;
std::cout << dynamic_cast<Foo*>(&b) << std::endl;
std::cout << dynamic_cast<Bar*>(&b) << std::endl;
}
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
}
If I have a class that's inheriting from another, is it possible to replace the inherited class in the child? I've got a demo of what I'm trying to do below, but I'm not sure the syntax.
#include <iostream>
class singleNum
{
public:
int m_a;
singleNum(int a)
{
std::cout << "SETUP" << std::endl;
m_a = a;
}
~singleNum()
{
std::cout << "CLOSEDOWN" << std::endl;
}
};
class inheritor : public singleNum
{
public:
inheritor(int a) : singleNum(a) {};
reset(int b)
{
singleNum::this = *singleNum(b);
}
};
int main()
{
inheritor z(5);
std::cout << z.m_a << std::endl;
z.reset(5);
return 0;
}
No
You cannot exchange or reset the base class. If it had a reset method of it's own, you could call this, but you cannot call the constructor again.
If you want to do this, you should favor composition over inheritance. You can then create a completely new instance of the inner composition class and replace your existing instance.
Your current demo isn't hard to implement, but you'll need to modify the parent class:
#include <iostream>
class singleNum
{
public:
int m_a;
singleNum(int a)
{
std::cout << "SETUP" << std::endl;
reset(a);
}
~singleNum()
{
std::cout << "CLOSEDOWN" << std::endl;
}
virtual void reset(int b)
{
m_a = b;
}
};
class inheritor : public singleNum
{
public:
inheritor(int a) : singleNum(a) {}
void reset(int b) override
{
singleNum::reset(b);
}
};
int main()
{
inheritor z(5);
std::cout << z.m_a << std::endl;
z.reset(5);
return 0;
}
But this is the closest you will get to "replacing the base class". If your case is different than the demo presented and you need to call the base class constructor on an already constructed derived object then no, this is not doable.
I am trying to deal with abstract class argument, trying to figure out what to do, after running this code below getting the error : "In function 'int main()': 67:12: error: expected primary-expression before ')' token"
#include <iostream>
#include <string>
using namespace std;
class base1 {
protected:
int i;
public:
base1(int x) {
i=x;
cout << "Constructing base1\n";
}
virtual ~base1() {
cout << "Destructing base1\n";
}
};
class derived: public base1 {
int j;
public:
derived(int x, int y): base1(y){
j=x;
cout << "Constructing derived\n";
}
~derived() {
cout << "Destructing derived\n";
}
void show() {
cout << i << " " << j << " " << "\n";
}
};
class Isolver
{
public :
Isolver(){};
virtual ~ Isolver(){};
virtual void x(base1* pboard)=0;
};
class vr:public Isolver
{
void x(base1* pboard)
{
cout << "My virtual fun and base constructor are not working\n"<<endl;
};
};
int main()
{
vr obj;
obj. x(10, );
derived ob(3,4);
ob.show();
return 0;
}
Like Paul Rooney pointed out the comma inside obj.x(10,) should not be there because with the comma the compiler is expecting two arguments and since there is nothing after the comma it shows an error.
This is what you need to do inside main:
vr obj;
base1 b(1);
obj. x(&b);
or this:
vr obj;
derived ob(3,4);
obj. x(&ob);
ob.show();
and inside class vr
class vr:public Isolver
{
public:
void x(base1* pboard)
{
cout << "My virtual fun and base constructor are not working\n"<<endl;
}
};
#include <iostream>
using namespace std;
class A {
private:
int nVal;
public:
void Fun()
{
cout << "A::Fun" << endl;
}
void Do()
{
cout << "A::Do" << endl;
}
};
class B :public A {
public:
virtual void Do()
{
cout << "B::Do" << endl;
}
};
class C :public B {
public:
void Do()
{
cout << "C::Do" << endl;
}
void Fun()
{
cout << "C::Fun" << endl;
}
};
void Call(B& p)
{
p.Fun(); p.Do();
}
int main() {
C c; Call(c);
return 0;
}
In the above code, the output is
A::Fun
C::Do
But I cannot understand. in the function call(B& p), the reference p should refer to c from C class, so why the output is not
C::Fun
C::Do
When announcing a a basis class reference to a derived class, is the different basis class making any sense?
The problem is that A::Fun is not marked as virtual, therefore it doesn't find C::Fun at run-time. You should mark it as such:
class A {
private:
int nVal;
public:
virtual void Fun()
{
cout << "A::Fun" << endl;
}
// ...
wandbox example
This is a great example of an error that could be caught at compile-time thanks to the override specifier:
class C :public B {
public:
void Do() override
{
cout << "C::Do" << endl;
}
void Fun() override
{
cout << "C::Fun" << endl;
}
};
Would print:
error: 'void C::Fun()' marked 'override', but does not override
void Fun() override
^~~
wandbox example
I'm having trouble on my c++ code ..
class GrandParent {
public:
GrandParent()
{
printMe();
}
virtual void printMe()
{
std::cout << "GrandParent: printme" << std::endl;
}
}
class Parent : public GrandParent {
public:
Parent(){}
virtual void printMe()
{
std::cout << "Parent: printMe!" << std::endl;
}
}
class Child : public Parent {
public:
Child(){}
void printMe()
{
std::cout << "Child: printMe!" << std::endl;
}
}
int main()
{
Child *p = new Child();
delete p;
}
When I run this code, it prints "GrandParent: printMe".
my goal is to print "Child: printMe!". Is there something wrong in overriding printMe?
What you're trying to do isn't possible. At the time of GrandParent's constructor, the only part of the Child object that has been constructed and initialized is the GrandParent part - including the vtable. That is, when you call printMe(), the entry will be GrandParent's. It's only after Child gets constructed that the vtable entry for printMe() gets updated to point to Child::printMe.
Note that it's good that C++ works like this. If Child::printMe had been the one called, then you'd be calling a member function on a not-yet-constructed object. Nothing good can come of that.
Short answer: That's how C++ works.
When a virtual method is called from the constructor, not the method of the runtime class is used. Instead the method of the compile time class is used.
But there might be an escape using the Curiously Recurring Template Pattern as shown here:
#include <iostream>
template <class T>
class Base
{
protected:
Base()
{
T::printMe();
}
};
class GrandParent : Base<GrandParent>
{
public:
GrandParent()
: Base<GrandParent>()
{}
static void printMe()
{
std::cout << "GrandParent: printMe!" << std::endl;
}
};
class Parent : public GrandParent, public Base<Parent>
{
public:
Parent()
{}
static void printMe()
{
std::cout << "Parent: printMe!" << std::endl;
}
};
class Child : public Parent, public Base<Child>
{
public:
Child()
{}
static void printMe()
{
std::cout << "Child: printMe!" << std::endl;
}
};
int main()
{
GrandParent a;
std::cout << "..." << std::endl;
Parent b;
std::cout << "..." << std::endl;
Child c;
std::cout << "..." << std::endl;
}
Output:
GrandParent: printMe!
...
GrandParent: printMe!
Parent: printMe!
...
GrandParent: printMe!
Parent: printMe!
Child: printMe!
...
But yeah, then you have to deal with static methods and multiple inheritence.