class base {
public:
int foo();
int foo(int a);
int foo(char* b);
int doSomething(int);
}
class derived : public base
{
public:
int doSomething(int b);
}
int derived::doSomething( int b)
{
base::doSomething(b);
//Make Something else
}
int main()
{
derived d= new derived();
d->foo();
}
now in the foo method (any of them) i want to call the more specific doSomething. if i instance a derived class i want the doSomething of the derived class, and if i instance a base class i want the doSomething of the base class, in spite of i'm calling from the foo method implemented in the base class.
int base::foo()
{
//do something
makeSomething(5);
}
In your base class, make the doSomething method virtual:
public:
virtual int doSomething(int);
Then you can:
Base* deriv = new Derived();
Base* base = new Base();
deriv->doSomething();
base->doSomething();
And enjoy!
That is what virtual functions are for:
struct A {
virtual ~A() {}
virtual void f() {}
};
struct B : A {
void f() {}
};
// ...
A* a = new A;
A* b = new B;
a->f(); // calls A::f
b->f(); // calls B::f
The C++ FAQ lite covers some details, but can't substitute a good introductory book.
I would propose this example as to illustrate difference between use of virtual or non-use
struct A {
virtual ~A() {}
virtual void f() {}
void g() {}
};
struct B : A {
void f() {}
void g() {}
};
A* a = new A;
A* b = new B;
a->f(); // calls A::f
b->f(); // calls B::f
b->g(); // calls A::g
Related
I have an abstract class A with the pure virtual method void foo(int a) = 0
Then I have several classes that inherit from A and all of them define the method foo. But I need one of them, B, to make it so foo takes an extra parameter, int b, so sort of an overload.
Then I would like to do this:
A *bInstance = new B();
bInstance -> foo(1, 2);
But I get an error telling me that foo is taking too many parameters.
Writing this, I realize it's kind of a weird thing to do so maybe you can't do this and it's good that you can't do it. But in case it is possible, please do tell me how I should go about it.
You can use the overloaded function of B only if the pointer to use is of type B.
See:
#include <iostream>
#include <memory>
class A{
public:
virtual void foo(int a) = 0;
};
class B : public A
{
public:
virtual void foo(int a) override
{
}
void foo(int a, int b)
{
std::cout << a << "," << b;
}
};
int main(){
auto b = std::make_shared<B>();
b->foo(1, 2);
//to use a:
A* aPtr = b.get();
aPtr->foo(1);
return 0;
}
Although Bernd's answer is a possiblility, you must ask yourself what the effect of an overload is. E.g., think of the following.
std::unique_ptr<A> bAsA = std::make_unique<B>();
bAsA->foo(1, 2); // no worky.
bAsA->foo(1); // works, but what should it do?
It there's a different interface between A and B, I would suggest to add a layer of abstraction in form of a new base class (which I will call C).
So instead of
struct A {
// common
virtual void bar() {}
// class specific
virtual void foo(int) = 0;
};
struct B: public A {
// weird unused override which is still available
void foo(int) override {}
// class specific
void foo(int, int) {}
};
use
struct C {
// common
virtual void bar() {}
};
struct A: public C {
// class specific
virtual void foo(int) = 0;
};
struct B: public C {
// class specific
void foo(int, int) {}
};
You can fully achieve want you want using a default parameter:
class A
{
public:
virtual void foo(int a, int b = 0) = 0;
virtual ~A() = default;
};
class B : public A
{
public:
void foo(int a, int b) override { }
};
class C : public A
{
public:
void foo(int a, int b = 0) override { }
};
int main()
{
A* b = new B();
A* c = new C();
b->foo(1, 2);
c->foo(1);
}
You don't have to use this parameter in C::foo implementation (and any other derived classes) if you don't need to.
So to summarize I have something equivalent to
class A{
public:
virtual void foo() const = 0;
};
class B : public A{
public:
B(){};
void foo() const override{
//some code
};
};
class C{
public:
C(){};
B someFunction();
private:
A* x;
};
and A* x; points to some B object and I need someFuntion() to return that object that x is pointing to. I've tried just doing return *x but that doesn't work.
You must down-cast the x into B before de-reference.
class C
{
public:
C() {};
B someFunction()
{
return *static_cast<B*>(x); // like this
}
private:
A* x = new B;
};
You need also provide the virtual ~A(), not to have undefined behavior.
When to use virtual destructors?
class A
{
public:
virtual void foo() const = 0;
virtual ~A() = default;
};
If you know that x points to a B object then cast it first.
return *static_cast<B*>(x);
I have:
class A
{
public:
virtual some_type foo();
protected:
virtual some_type bar();
}
class B : public A
{
protected:
some_type bar() override;
}
// std::shared_ptr<B> b_ptr;
b_ptr->foo();
Where A::foo calls bar. For some reason that I cannot seem to understand, A::bar is being called insted of B::bar. Is there any way to ensure B::bar is called instead?
EDIT:
some_type A::foo() {
this->bar();
}
EDIT 2:
Class was instantiated as A, and then cast to B, hence the shared pointer to B was invalid.
It depends.
If foo() calls bar() in this way:
some_type foo(){ A::bar(); }
This is compile time binding, and so the compiler will bind that call to A::bar() even if the dynamic type is B.
Instead, if foo() calls bar() in this way:
some_type foo(){ this->bar(); /*or just bar(), same thing*/}
Then because bar() is virtual, the binding will be resolved at runtime, and so it will call the bar() function for the dynamic type, thus B::bar().
So this code:
class A
{
public:
virtual void foo(){this->bar();};
protected:
virtual void bar(){cout<<"A";};
};
class B : public A
{
protected:
void bar() override{cout<<"B";};
};
int main() {
std::shared_ptr<B> b_ptr(new B);
b_ptr->foo(); // B
}
Will print B, but this code:
class A
{
public:
virtual void foo(){A::bar();};
protected:
virtual void bar(){cout<<"A";};
};
class B : public A
{
protected:
void bar() override{cout<<"B";};
};
int main() {
std::shared_ptr<B> b_ptr(new B);
b_ptr->foo(); // A
}
will print A
I'm fairly new to object-oriented program, so maybe this is a basic question, but I'd appreciate any help you can offer.
If I have a class B, which is derived from class A, is there some way for objects of class B to access class B's member functions from within member functions of class A? So in the example below I might have a call to function2 from within function1 if the object initially calling function1 is of type B. Is this possible, and if so, how do I accomplish it? Thanks!
class A
{
public:
int a;
int b;
A(){}
A(int a, int b) { this->a = a; this->b = b; }
int function1();// { call function2 if class B }
};
class B : public A
{
public:
int c;
int d;
B(){}
B(int c, int d) { this->c = c; this->d = d; }
int function2();
};
A function inside A doesn't have any idea of the fact that a class B which extends A exists and which methods it has.
To be able to invoke a specific method implemented in B from A you need to declare it in A as virtual, possibly pure virtual (= 0).
class A {
protected:
virtual void function2() = 0;
public:
void function1() { this->function2(); }
}
class B : public A {
protected:
void function2() override { ... }
}
A virtual method is resolved at runtime, this means that when invoked, the more specific implementation for the object on which it is called is executed. A pure virtual method doesn't have any base implementation, this makes A abstract and forbids its instantiation.
EDIT: a final note, don't call virtual methods from base constructors or destructors. It is dangerous and a bad practice, not that this is your case but you never know.
Yes. You need to define function2() as a virtual function in class A. Then calling it from function1 will result in B's function2() being called if the object is actually a B. For example:
class A
{
public:
int a;
int b;
A(){}
A(int a, int b) { this->a = a; this->b = b; }
int function1() { return this->function2(); }
virtual int function2() { return 0; }
};
class B : public A
{
public:
int c;
int d;
B(){}
B(int c, int d) { this->c = c; this->d = d; }
int function2() override { return 999; }
};
If there is no sensible implementation of function2 for A, then it would never make sense to have an A object. You can express this by declaring function2 to be pure virtual; e.g.
virtual int function2() = 0;
virtual allows you to override function in parent class.
class A
{
public:
A(){}
A(int a, int b):a(a), b(b) {}
int function1() { return this->function2(); }
virtual int function2() { //what function2 in parent class should do }
private:
int a;
int b;
};
class B : public A
{
public:
B(){}
B(int c, int d):c(c), d(d) {}
int function2() { //what function2 in child class should do }
private:
int c;
int d;
};
I have class A and class B, for instance this is the code
class A{
void show(){.....}}
class B:public A{
void show(){....}}
void main()
{ int arr[2];
arr[0]=new A();
arr[1]=new B();
arr[1]->show();
}
in this situation I want the show of class B to action, but no matters what I did it always go to ths 'show' of the parent..
what can I do?
You must make it a virtual method in the base class, also the array should be A* in your case not int. Then these two point will solve your problem:
struct A
{
virtual void show() {}
//^^^^^^^
};
struct B : public A
{
void show() {}
/* virtual void show() override {} */
};
int main()
{
A *arr[2];
arr[0] = new A;
arr[1] = new B;
arr[1]->show();
}
Last word, avoid bare pointers, you can use smart pointers such as unique_ptr or shared_ptr:
struct A
{
virtual void show() {};
};
struct B : public A
{
void show() {}
/* virtual void show() override {} */
};
int main()
{
unique_ptr<A> arr[2];
arr[0].reset(new A);
arr[1].reset(new B);
arr[1]->show();
}