0

I am having a base class that has 5 subclasses.

If in my base class I have this:

virtual CpuPort &getsecondDataPort()=0;

then this means that the method has to be implemented for all the subclasses, right?

But I do not want that, since I know that I will call that method only when I have an object of the specific subclass so I thought that I could write this instead:

virtual CpuPort &getsecondDataPort();

and implement it only in the subclass I want. But that gives me this error:

/base.cc:254: undefined reference to `vtable for BaseCPU'

and in the from the other subclasses :

undefined reference to `typeinfo for BaseCPU'

where BaseCPU is my object of the base class.

Because it is part of a bigger library (simulator actually), I want to make as fewer changes as possible. So please do not suggest something like 'define that oonly in your subclass' as I want to follow the way code is organized so far, unless this is the only way of fixing the problem.

Any idea on why that might happen?

Thanks

ghostrider
  • 5,131
  • 14
  • 72
  • 120
  • possible duplicate of [C++ Virtual/Pure Virtual Explained](http://stackoverflow.com/questions/1306778/c-virtual-pure-virtual-explained) – Kate Gregory Apr 20 '13 at 13:21

3 Answers3

3

this means that the method has to be implemented for all the subclasses, right?

Only if you want to create direct instances of those subclasses. If a subclass does not implement a pure virtual function, it will be abstract - which is allowed per se.

But that gives me this error:

This is because the virtual function is declared, but not defined. You have to provide a definition if the function is not pure virtual.

In this case, you can not provide a dummy implementation that does nothing, because your function is supposed to return a reference, and flowing off the end of a value-returning function without returning anything is Undefined Behavior per Paragraph 6.6.3/2 of the C++11 Standard.

If your base class has a data member of type CpuPort called (say) myCpuPort, on the other hand, you could do this:

virtual CpuPort &getsecondDataPort() { return myCpuPort; }
Andy Prowl
  • 124,023
  • 23
  • 387
  • 451
  • 1
    @ghostrider: If you have to create direct instances of those derived classes, and the function is pure virtual in the base class, then yes, you have to *declare it and define it* in all derived classes. – Andy Prowl Apr 20 '13 at 13:29
  • @ghostrider: consider that the point of runtime polymorphism is for code to be able to operate on any of the derived types using the functions declared virtual in the base class. If it were legal for there to be no function definition in the base nor a derived class, then what's supposed to happen when that function gets called with the wrong derived type? Where's the calling code going to get a valid CpuPort reference from? You might want to read about the Liskov Substitution Principal, which explains why and how derived types should honour the base class interface. – Tony Delroy Apr 20 '13 at 13:56
1

Seems the only solution is to provide an empty implementation in the base class (considering your restraints).

Think about the following scenario:

 struct Base
 {
    virtual void foo() = 0;
 };
 struct Derived1
 {
 };
 struct Derived2
 {
    virtual void foo() {};
 };

 Base* p1 = new Derived1;
 Base* p2 = new Derived2;
 p1->foo();
 p2->foo();

Say the compiler let this code pass (it doesn't, and that's good). What would happen on the second call?

Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
1

You have declared the member function but not defined it. You need to provide an implementation of getsecondDataPort.

CpuPort& BaseCPU::getsecondDataPort()
{
     return somevar_;
}
Captain Obvlious
  • 19,754
  • 5
  • 44
  • 74
  • so I have to define it, in every subclass, right? I wanted to avoid that, but ok! – ghostrider Apr 20 '13 at 13:28
  • @ghostrider Not necessarily, I could have worded that better (see Andy's answer). You could very well end up with a common base implementation that inherits from BaseCPU but only includes some of those methods and handles tasks that are common to all derived classes. I haven't seen the rest of your class hierarchy so it's hard to say. – Captain Obvlious Apr 20 '13 at 13:33