How to detect whether a class is used polymorphically? - c++

Suppose in one old project (>1M lines), there is a class named Base which has two virtual functions foo and bar
class Base
{
public:
virtual void foo();
virtual void bar();
};
class Derived: public Base
{
public:
virtual void foo();
virtual void bar();
};
I suspect that Base is not used polymorphically, so foo/bar should not be virtual.
To confirm my ideas, I need to find out whether there is a statement like:
Base *b = new Derived;
but if we pass the pointer among a function, it would be hard to find out, for example:
Base *f()
{
...
Derived *d = /* ... */;
...
return d;
}
Is there any way to do that?

Make Derived inherit privately from Base. This will prevent implicit upcasts making Base* b = new Derived; a compile error.

If you have two classes like following:
class Base
{
virtual void a(){};
};
class Derived : public Base
{
virtual void b(){};
};
when you write code:
Base* ptr = new Derived();
you could see ptr in watch window
ptr->__vfptr 0x00eb5740 const Derived::`vftable' *
[0] 0x00eb1028 Base::a(void) *
You can look at the entire vtable if you add this helper variable:
void (**vt)() = *(void (***)())ptr;
and in watch window you could see:
vt,2 0x00eb5740 const Derived::`vftable' void (void)* *
[0] 0x00eb1028 Base::a(void) void (void)*
[1] 0x00eb10aa Derived::b(void) void (void)*
so ,you could take a try.

Related

DerivedA pointer pointing to DerivedB

I have a base class which serves as an interface (if I use that word correctly). The idea is that the base class has some derived classes that implement one virtual function of the base class. Then I also need another class that extends the base class (lets call it extended base). What I would like is that I can store a class derived from base into an extended base pointer.
MWE:
class Base {
public:
virtual ~Base();
virtual double value();
}
class Derived : public Base{
public:
double value() override {return 5;}
}
class ExtendedBase : public Base {
public:
virtual ~ExtendedBase ();
virtual double value2(){return 10;}
}
int main() {
ExtendedBase * object;
object = new Derived();
std::cout << object->value(); //should give implementation in Derived, i.e. 5
std::cout << object->value2(); //should give implementation in ExtendedBase, i.e. 10
delete object;
return 0;
}
With this MWE I get a compile error at the second line in the main. error: cannot convert 'Derived*' to 'ExtendedBase*' in assignment object = new Derived();. Part of me understands why it doesn't work (although I can't explain), but I would like to know if I can get the desired behaviour in some other way.
P.S. Sorry about the bad question name, I couldn't think of another way to keep it short
P.S.2 I know raw pointers like this are not advised. In the future I will change to smart pointers but I don't think they are needed for this simple example
ExtendedBase and Derived are each derived from Base. If you want to use an ExtendedBase* pointer to point to a Derived object, you will need to derive Derived from ExtendedBase.
To use a different example,
class Feline{
virtual void run();
}
class Housecat : Feline{
void run() {}
}
class BigCat : Feline{
virtual void run();
virtual void roar();
}
Here Feline, Housecat, and BigCat are analogous to Base, Derived, and ExtendedBase. BigCat and Housecat are each Feline, but since Housecat is not a BigCat, you can't use a BigCat* pointer to point to a Housecat.
This is the desired behavior from a language architect perspective.
For instance, if you have
class Ship
{
public:
virtual void move() = 0;
}
class Steamboat : public Ship
{
public:
virtual void move() override { ... }
}
class Sailboat : public Ship
{
public:
virtual void move() override { ... }
virtual void setSails() { ... }
}
Now, you don't want a Steamboat to become a Sailboat all of a sudden, hence:
Steamboat* tootoo = new Sailboat;
cannot be valid.
That's why your code cannot work. Conceptually.
So giving a quick fix is not possible, because your concept is not really clear.
When you are assigning an address to a pointer that means you should be able to access all the members of the type the pointer is pointing to through the pointer.
For ex,
class B {};
class D : B {};
B *p = new D();
now through p, at least you can access all the members of base portion of the derived class.
But in your code,
ExtendedBase * object;
object = new Derived();
object should be able to access all the members of ExtendedBase portion of the derived class. But how is it possible as derived class is not derived from ExtendeBase. So compiler is throwing error.
You need to do some changes in your code to work.
To make base as interface (abstract class), you need to define at
least one member function as pure virtual.
If you want to access the member function of ExtendedBase through
Base pointer, you should define same function 'val' in your
ExtendedBase.
Below are the changes.
#include <iostream>
using namespace std;
class Base {
public:
virtual ~Base() {};
virtual double value() = 0;
};
class Derived : public Base{
public:
~Derived() {};
double value() {
return 5;
}
};
class ExtendedBase : public Base {
public:
virtual ~ExtendedBase () {};
double value()
{
return 10;
}
};
int main() {
Base *p = new Derived();
std::cout << p->value() << std::endl;
delete p;
Base *p1 = new ExtendedBase();
std::cout << p1->value() << std::endl;
delete p1;
return 0;
}

How to call a method that expects a subclass object with an subclass object referenced by a pointer to its superclass?

I have an object that is referenced by a pointer to its superclass: Base* d1 = new Derived();
I would like to pass it to another method that expects an object of the derived class: void f(Derived* d);
But it doesn't work unless I use type-casting. Is there another way to achieve this?
Here is an example:
#include <stdio>
class Base {};
class Derived : public Base {};
class Client
{
public:
void f(Base* b) { printf("base"); };
void f(Derived* d) { printf("derived"); };
};
int main(int argc, char* argv[])
{
Client* c = new Client();
Base* b = new Base();
Base* d1 = new Derived();
Derived* d2 = (Derived*) d1;
c->f(b); // prints "base". Ok.
c->f(d1); // prints "base"! I expected it to be "derived"!
c->f(d2); // prints "derived". Type-casting is the only way?
}
Generally speaking, you can do some stuff with dynamic_cast.
From the other side I believe, that dynamic_cast can practically always be avoided by the good design.
In your example you can make function f virtual member of Base class and override it in the Derived class. Then call it f via pointer to Base.
Something like this:
class Base {
public:
virtual void f() {
printf("Base\n");
}
};
class Derived : public Base {
public:
virtual void f() {
printf("Derived\n");
}
};
class Client
{
public:
void f(Base* b) {
b->f();
};
};

Why can't we call virtual function in base class using object of base class in case the virtual function is not overridden in child class?

I have an example code snippet:
class A
{
public:
virtual void func1();
virtual void func2();
};
class B
{
public:
virtual void func2();
virtual void func3();
};
void main()
{
A *obj = new B;
obj->func3();
}
Why does the line obj->func3(); return error?
(we know that a separate virtual table is created for each class)"
Because obj is a pointer to A. A doesn't have func3 on it, so you can't call it.
Note: I've assumed you actually wanted to inherit B from A - it would error before the call, on the assignment in current state.
There's no way this could possibly work. Consider:
Class B : public A
{
void Foo (int);
};
class C : public A
{
void Foo (char);
};
class D : public A
{
void Foo (double);
}
void bar (A* obj)
{
obj->Foo (1); // Uh oh!
}
How can the compiler know what code to generate? Should this pass an integer? A float? A character?
And it's never safe, because the compiler is not able to see the definitions of all the derived classes when it's compiling functions like bar.
If you want to call a function through pointers to a base class, the base class needs to at least define what parameters that function takes.
Your code should look like this if it needs to work. You need to declare the function in base class otherwise in vtable for func3() it space will not be alloted in base class.
class A
{
public:
virtual void func1();
virtual void func2();
virtual void func3(); //virtual function , linking at run time depends on what object it points to
};
class B : public A //public inheritance
{
public:
virtual void func2();
virtual void func3();
};
void main()
{
A *obj = new B; //base class pointer pointing to derived class object
obj->func3(); //since func3() is declared as virtual , dynamic linking takes place and since at
// run times it points to object b , function in class B is invoked
}

assigning derived class pointer to base class pointer in C++

I have following
class base
{
};
class derived : public base
{
public:
derived() {}
void myFunc() { cout << "My derived function" << std::endl; }
};
now I have
base* pbase = new derived();
pbase->myFunc();
I am getting error myFunc is not a member function of base.
How to avoid this? and how to make myFunc get called?
Note I should have base class contain no function as it is part of design and above code is part of big function
If you are adamant that this function should NOT be a part of base, you have but 2 options to do it.
Either use a pointer to derived class
derived* pDerived = new derived();
pDerived->myFunc();
Or (uglier & vehemently discouraged) static_cast the pointer up to derived class type and then call the function
NOTE: To be used with caution. Only use when you are SURE of the type of the pointer you are casting, i.e. you are sure that pbase is a derived or a type derived from derived. In this particular case its ok, but im guessing this is only an example of the actual code.
base* pbase = new derived();
static_cast<derived*>(pbase)->myFunc();
myfunc needs to be accessible from the base class, so you would have to declare a public virtual myfunc in base. You could make it pure virtual if you intend for base to be an abstract base class, i.e one that cannot be instantiated and acts as an interface:
class base
{
public:
virtual void myfunc() = 0; // pure virtual method
};
If you ant to be able to instantiate base objects then you would have to provide an implementation for myfunc:
class base
{
public:
virtual void myfunc() {}; // virtual method with empty implementation
};
There is no other clean way to do this if you want to access the function from a pointer to a base class. The safetest option is to use a dynamic_cast
base* pbase = new derived;
....
derived* pderived = dynamic_cast<derived*>(pbase);
if (derived) {
// do something
} else {
// error
}
To use the base class pointer, you must change the base class definition to be:
class base
{
public:
virtual void myFunc() { }
};
I see no other way around it. Sorry.
You could add it as a member of base and make it a virtual or pure virtual function. If using this route however, you should also add a virtual destructor in the base class to allow successful destruction of inherited objects.
class base
{
public:
virtual ~base(){};
virtual void myFunc() = 0;
};
class derived : public base
{
public:
derived() {}
void myFunc() { cout << "My derived function" << std::endl; }
};

Interview question about virtual functions in C++

I was asked this crazy question.
I was out of my wits.
Can a method in base class which is declared as virtual be called using the base class pointer which is pointing to a derived class object?
Is this possible?
If you're trying to invoke a virtual method from the base class pointer, yes.
That's polymorphism.
If you're asking, with a base class pointer to a derived class, can you invoke a base class method that is overriden by the derived class? Yes that's also possible by explicitly scoping the base class name:
basePtr->BaseClass::myMethod();
Try:
class A { virtual void foo(); }
class B : public A { virtual void foo(); }
A *b = new B();
b->A::foo ();
You mean something like this. (Where pBase is of type pointer-to-base but the pointed-to object is actually of type Derived which is derived from Base.)
pBase->Base::method();
Yes, it's possible.
Yes -- you have to specify the full name though:
#include <iostream>
struct base {
virtual void print() { std::cout << "Base"; }
};
struct derived : base {
virtual void print() { std::cout << "Derived"; }
};
int main() {
base *b = new derived;
b->base::print();
delete b;
return 0;
}
If I understand the question correctly, you have
class B
{
public:
virtual void foo();
};
class D: public B
{
public:
virtual void foo();
}
B* b = new D;
And the question is, can you call B::foo(). The answer is yes, using
b->B::foo()
class B
{
public:
virtual void foo();
};
class D: public B
{
public:
virtual void foo();
}
B* b = new D;
Try calling
(*b).foo()
to invoke base class foo function
class B {
public: virtual void foo();
};
class D: public B {
public: virtual void foo()
{
B::foo();
};
}
B* b = new D;
Solutions :
b->foo();
b->B::foo()
OR do not override/define foo() in the derived class D and call b->foo()
B objb = *b; objb.foo() ; // this is object slicing and not (*b).foo() as in one of the previous answers
No. Not in a clean way. But yes. You have to do some pointer manipulation, obtain a pointer to the vtable and make a call. but that is not exactly a pointer to base class, but some smart pointer manipulation. Another approach is using scope resolution operator on base class.