I am trying to use a pure virtual class as a parameter in a program, however, i get a compile error:
Error 1 error C2259: 'Person': cannot instantiate abstract class
I guess the error im getting is because A) its not possible to instantiate an abstract class and B) i can't use an abstract class as i would use an interface in C#
The C# program below illustrates what im trying to do in the C++ program. How can i write generic code using abstract classes in C++? if im forced to use a more specialized version of Person e.g. Employee, the code is not really generic. Do i have to use templates?
#include<iostream>
#include<vector>
class Person {
public:
virtual std::string getName() = 0;
virtual void setName(std::string name) = 0;
virtual std::string toString() = 0;
private:
std::string name;
};
class Employee : public Person {
public:
std::string getName() {
return this->name;
}
void setName(std::string name) {
this->name = name;
}
std::string toString() {
return "name:" + this->name;
}
private:
std::string name;
};
class Repository {
public:
void add(Person& p) {
this->repo.push_back(p);
}
private:
std::vector<Person> repo;
};
int main(int argc, char* argv[])
{
Repository repo;
Employee emp1;
emp1.setName("John Doe");
repo.add(emp1);
return 0;
}
interface IPerson
{
string GetName();
void SetName(string name);
string ToString();
}
class Employee : IPerson
{
private string _name;
public string GetName() {
return this._name;
}
public void SetName(string name) {
this._name = name;
}
public override string ToString() {
return "name: " + this._name;
}
}
class Repository
{
private List<IPerson> _repo;
public Repository() {
this._repo = new List<IPerson>();
}
public void Add(IPerson p) {
this._repo.Add(p);
}
}
class Program
{
static void Main(string[] args)
{
Repository repo = new Repository();
Employee emp1 = new Employee();
emp1.SetName("John Doe");
repo.Add(emp1);
}
}
The problem is that Repository
is storing Person
objects, and this class cannot be instantiated*. This is because std::vector<Person>
holds Person
values.
You can store pointers to Person
instead, but you have to ensure they live at least as long as the Repository
instance. For example,
/// class repository does not own Persons it holds
class Repository {
public:
void add(Person& p) {
this->repo.push_back(&p);
}
private:
std::vector<Person*> repo;
};
* Note that in general it is possible to construct a base class object from a derived type one. The base object would be constructed from the base sub-object of the derived one (see What is object slicing?). In your case, this fails because the base type is abstract.