Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

g++ "because the following virtual functions are pure" with abstract base class

Here is my example code which produces the error:

struct Impl
{
  int data_size_;
  int find(int var){return 0;}
  int get(int rowid){return 0;}
};

class Container
{
public:
  Container() {}
  virtual ~Container() {}
  virtual int get_size() = 0;
  virtual int get(int rowid) = 0;
};


class SortedContainer : virtual public Container {
public:
  virtual int find(int var) = 0;
};

class ContainerImpl : public Container
{
protected:
  Impl impl_;
public:
  int get_size() {return impl_.data_size_;}
  int get(int rowid) {return impl_.get(rowid);}
};

class SortedContainerImpl
  : public SortedContainer, public ContainerImpl
{
private:
  typedef ContainerImpl Base;
public:
  int find(int var){return Base::impl_.find(var);}
};

ContainerImpl ci;
SortedContainerImpl sci;

it seems "SortedContainerImpl" went wrong while "ContainerImpl" is fine.

g++ complains:

example_b.cpp:42:21: error: cannot declare variable ‘sci’ to be of abstract type ‘SortedContainerImpl’
example_b.cpp:32:7: note:   because the following virtual functions are pure within ‘SortedContainerImpl’:
example_b.cpp:13:15: note:  virtual int Container::get_size()
example_b.cpp:14:15: note:  virtual int Container::get(int)

I inheret SortedContainerImpl from ContainerImpl in order to reuse get_size() and get(int)

I'm not familiar with c++, What's the nature of this problem and How can I fix it?

Thanks all.

like image 874
tdihp Avatar asked Sep 27 '12 07:09

tdihp


People also ask

Does abstract class contains pure virtual function?

CPP. Some Interesting Facts: 1) A class is abstract if it has at least one pure virtual function. In the following example, Test is an abstract class because it has a pure virtual function show().

What is a pure virtual function and abstract class?

An abstract class is a class that is designed to be specifically used as a base class. An abstract class contains at least one pure virtual function. You declare a pure virtual function by using a pure specifier ( = 0 ) in the declaration of a virtual member function in the class declaration.

Is pure virtual function and abstract class same?

A pure virtual function is a virtual function in C++ for which we need not to write any function definition and only we have to declare it. It is declared by assigning 0 in the declaration. An abstract class is a class in C++ which have at least one pure virtual function.

Is a pure virtual function is defined in the base class?

A pure virtual function is a member function of base class whose only declaration is provided in base class and should be defined in derived class otherwise derived class also becomes abstract. Classes having virtual functions are not abstract. Base class containing pure virtual function becomes abstract.


2 Answers

In C++ Once you have an pure virtual member function your class becomes abstract class and you cannot create any objects of it.
Such a class is not meant to be instantiable by itself.It is meant to act as an Interface. One would derive from such an abstract class and provide implementations of all the pure virtual functions in the derived class.

Note that your class SortedContainerImpl derives from two classes SortedContainer and ContainerImpl.
SortedContainer in turn derives from Container but it never implements the pure virtual functions.

like image 74
Alok Save Avatar answered Sep 27 '22 18:09

Alok Save


Your SortedContainerImpl class has two separate Container base classes. One is virtual (via the SortedContainer class) and the other is non-virtual (via the ContainerImpl class).

SortedContainerImpl has concrete implementations of Container::get_size() and Container::get(int) for the base that comes in from ContainerImpl, but not for the virtual base that comes in via SortedContainer.

One way to fix the problem is to give concrete implementations in SortedContainerImpl:

class SortedContainerImpl
  : public SortedContainer, public ContainerImpl
{
private:
  typedef ContainerImpl Base;
public:
  int find(int var){return Base::impl_.find(var);}

  int get_size() {return ContainerImpl::get_size();}
  int get(int rowid) {return ContainerImpl::get(rowid);}
};

Another way would be to make Container a virtual base class of ContainerImpl, so SortedContainerImpl would only get the one, virtual, base Container:

class ContainerImpl : virtual public Container
{
protected:
  Impl impl_;
public:
  int get_size() {return impl_.data_size_;}
  int get(int rowid) {return impl_.get(rowid);}
};
like image 36
Michael Burr Avatar answered Sep 27 '22 18:09

Michael Burr