with this code:
class Plant
{
public:
virtual std::string getPlantName();
virtual void setPlantName(std::string s);
virtual std::string getPlantType();
virtual void setPlantType(std::string s);
};
class Carrot : public Plant
{
public:
Carrot();
~Carrot();
private:
std::string _plantName;
};
and then:
#include "Carrot.hpp"
Carrot::Carrot()
{
}
Carrot::~Carrot() { }
std::string Carrot::getPlantName() { return _plantName; }
I am getting a link error:
Carrot.cpp:16:21: Out-of-line definition of 'getPlantName' does not match any declaration in 'Carrot'
So the goal here is to create a Plant class where other classes extend like class Carrot : public Plant
But, what I am not sure about is could I just inline the functionality in Plant so that I dont have to create these get and set functions in each class like Carrot or Peas, etc?
if I did:
inline virtual std::string getPlantName( return _plantName; );
would that work? I would then add std::string _PlantName; to class Plant and then when I create Carrot from Plant I get all the same functions and Carrot will have variables like _plantName, etc, correct?
So this would be:
class Plant
{
public:
inline virtual std::string getPlantName( return _plantName; );
virtual void setPlantName(std::string s);
virtual std::string getPlantType();
virtual void setPlantType(std::string s);
private:
std::string _plantName;
};
class Carrot : public Plant
{
public:
Carrot();
~Carrot();
};
#include "Carrot.hpp"
Carrot::Carrot()
{
setPlantName(CARROT::plantName);
}
Carrot::~Carrot() { }
If all objects of the Plant class should have a type and a name, both std::strings, you probably want those common members in the base class:
// Plant.hpp
class Plant
{
public:
Plant();
virtual ~Plant(); // virtual destructor!
virtual std::string getPlantName();
virtual void setPlantName(std::string s);
virtual std::string getPlantType();
virtual void setPlantType(std::string s);
protected:
std::string _plantName;
std::string _plantType;
};
// Plant.cpp
#include <Plant.hpp>
std::string Plant::getPlantName() { return _plantName; }
void Plant::setPlantName(std::string s) { _plantName = s; }
... same for type
When creating a derived class using class Carrot : public Plant, that class will have the same data members and the same functions. You would also have the ability to override them if needed (thanks to the virtual keyword, derived classes' implementations will be called when using a Plant pointer to a Carrot object).
Note that if you want to make sure never to instansiate a Plant object, you should make any non-common functions (like a DoSomethingTypeSpecific() that a Carrot or a Flower would do differently) pure virtual and by that creating an abstract base class. All base classes would then have to implement those functions.
Inlining here does not make a real difference, it's just a matter of defining the functions in the header or in a separate .cpp file. Generally, it's a good idea to keep the implementation in a separate file but these small setters and getters could easily be inlined if you wanted to.
You could correct the error by adding the method to the class declaration:
class Carrot : public Plant
{
public:
Carrot();
~Carrot();
virtual std::string getPlantName();
private:
std::string _plantName;
};
Or, if all plants have names, you could define the method in the Plant class instead (likely in in plant.cpp). In fact, you have to define it unless you declare it to be pure virtual.
You need to declare the function.
class Carrot : public Plant
{
public:
Carrot();
~Carrot();
std::string getPlantName(); //Add this
private:
std::string _plantName;
};
A couple of notes:
It isn't strictly necessary for Carrot::getPlantName to be virtual, although many C++ developers consider it good form. I personally prefer to only use virtuals in abstract base classes, and use none in concrete classes
You probabally need to add virtual ~Plant() {} to the Plant class. You almost always want classes with virtual methods to also have virtual destructors.
Related
I am trying to design a parking system (Low-level Design )
Some classes behave like this.
class Vehicle
{
public:
int entryTime;
int exitTime;
virtual void leaveParking(Vehicle*);
virtual int getChargePerHr();
//virtual void getChargePerHr() = 0;
Vehicle() {}
};
class Car : public Vehicle
{
private :
int chargePerHr = 30;
public:
void leaveParking(Vehicle*);
int getChargePerHr();
Car(){}
};
class Bike : public Vehicle
{
private :
int chargePerHr = 10;
public:
void leaveParking(Vehicle*);
int getChargePerHr();
Bike(){}
}
void Vehicle ::leaveParking(Vehicle* v)
{
int pay = v-> // Here expecting Car class member function getChargePerHr() should come
//so that I can access private member chargePerHr of car class.
// But I am not able to access the Car class member function here.
}
int main()
{
Car c1; // assume Car c1 has already parked.
Vehicle v;
Vehicle* vptr = new Vehicle();
vptr = new Car();
c1.leaveParking(vptr); // Car c1 wants to leave the parking place
}
I want to access getChargePerHr() of Car class using Base class Vehicle member function.
I tried with pure virtual function but still could not make it.
Could anyone help me?
Problem
Here:
void Vehicle::leaveParking(Vehicle* v)
{
...
}
You're not able to access Car::getChargePerHr() because v is a Vehicle not a Car.
Clearly you're attempting to achieve polymorphism since it appears you want derived classes of Vehicle to perform the same actions when they leave parking.
Solution
Declare Vehicle::getChargePerHr() as pure virtual (or virtual if you want a default implementation)
Provide implementations of getChargePerHr() in your derived classes
Implement Vehicle::leaveParking() using just the methods you've defined in Vehicle
At runtime, the virtual table will resolve overrides and call the correct derived implementation.
Other Issues
You are inheriting from Vehicle without declaring its destructor virtual. This means if any child classes need to perform clean-up, their destructors won't be called.
You're missing a semicolon after the Bike class declaration.
If every Vehicle does the same thing when leaving parking, it doesn't make sense to have leaveParking() be virtual—you make a member function virtual if you want it to be able to be overridden by child classes.
Vehicle::leaveParking() should probably not be taking another Vehicle as a parameter. The function acts on the vehicle itself, not on a different one.
If your constructor is empty, it's better to leave it out of the class declaration since it can confuse others who might read your code.
And many more issues. I suggest you take aalimian's advice to read up on C/C++. Your code shows many misunderstandings.
Code
Putting everything together, here's an example:
class Vehicle
{
public:
int entryTime;
int exitTime;
virtual ~Vehicle() = default;
void leaveParking();
virtual int getChargePerHr() = 0;
};
void Vehicle::leaveParking()
{
// This will call a derived class's implementation
int pay = getChargePerHr();
// Do more vehicle stuff
}
class Car : public Vehicle
{
private:
int chargePerHr = 30;
public:
int getChargePerHr() override;
};
int Car::getChargePerHr()
{
return chargePerHr;
}
class Bike : public Vehicle
{
private:
int chargePerHr = 10;
public:
int getChargePerHr() override;
};
int Bike::getChargePerHr()
{
return chargePerHr;
}
You can see this in action here.
I use the Google Test framework to write unit tests for C++ code. Among other tests, I want to test the correct construction of objects of different classes that are all derived from one abstract class. Let's start with the abstract class:
class AbstractClass
{
public:
virtual ~AbstractClass() = default;
std::string getName() const { return name_; }
std::string toString() const { return toStringImpl(); }
protected:
AbstractClass(std::string name) : name_(name) {}
private:
virtual std::string toStringImpl() const = 0;
std::string name_;
};
It has the function getName() that is implemented by the abstract class itsself. And it has a toString() function whose implementation is delegated to the derived classes by the private pure virtual function toStringImpl(). toString() is not much of interest here, but its concept makes this class abstract.
I have two derived conctrete classes as follows:
class ConcreteClassA : public AbstractClass
{
public:
ConcreteClassA(std::string name) : AbstractClass(name) {}
private:
virtual std::string toStringImpl() const override { return ""; }
};
class ConcreteClassB : public AbstractClass
{
public:
ConcreteClassB(std::string name) : AbstractClass(name) {}
private:
virtual std::string toStringImpl() const override { return ""; }
};
Nothing special, just the fact that the constructor of the abstract class is called during the construction of these concrete classes.
If I want to test the correct construction, I can of course write all tests for all derived classes like in the following example where I include tests for functionalities of the abstract class:
class ConcreteClassATests : public ::testing::Test
{};
TEST_F(ConcreteClassATests, constructionSuccessful)
{
ConcreteClassA a {"TestA"};
ASSERT_EQ(a.getName(), "TestA");
}
class ConcreteClassBTests : public ::testing::Test
{};
TEST_F(ConcreteClassBTests, constructionSuccessful)
{
ConcreteClassB b {"TestB"};
ASSERT_EQ(b.getName(), "TestB");
}
Given m derived classes and n tests for content of the abstract class, this will result in m*n handwritten tests. I think this should be solved with n handwritten tests (resulting either in n or m*n executed tests).
I already read about Value-Parameterized Abstract Tests which sound promising and also about Typed Tests, but it looks like this would only apply to testing functions that receive input and output a result. I am not sure if those concepts can be applied to test for a correct construction of objects.
So, can someone tell me if it is somehow possible to define the test for an "abstract feature" only once?
To reproduce and run my example, all snippets can be put together into one source file. Just add the following two lines on top and link against gmock_main and pthread:
#include <string>
#include <gmock/gmock.h>
I'd welcome some help with C++ inheritance to get a better grasp of the concept.
Is it possible to "extend" member types when creating a derived class? I think my problem can be best demonstrated by a simple example, where I'd like to extend the class VehicleData with a new double variable:
class VehicleData {
int yearOfManufacture;
//Different routines, for example Serialize(), etc., warranting to create a class for just a bunch of variables
};
class BicycleData:VehicleData {
double frameHeight; //new property that only applies to bicycles
};
//Now I create the actual classes that use the types above
class Vehicle {
VehicleData data;
void PrintData(); //a function that works on basic vehicle data
};
class Bicycle:Vehicle {
BicycleData data; //should copy VehicleData when creating an instance of this class
};
The problem with this approach is that when I code the above and create a Bicycle instance, its BicycleData member hides the already existing VehicleData member.
Is there a way to extend the base class, i.e. simply add a new double variable (to store frame height in this example), and keep the already existing (year of manufacture) data?
As far as I can tell, there is no clean way to do exactly what you want with inheritance alone.
You could create a template out of your base class:
template <typename Data>
class BaseVehicle
{
Data data;
// etc.
};
class Vehicle : BaseVehicle<VehicleData>
{
// etc.
};
class Bicycle : BaseVehicle<BicycleData>
{
// etc.
};
Then the Vehicle and Bicycle classes would contain data field of VehicleData and BicycleData types respectively.
Since in your example Bicycle inherits from Vehicle privately (i.e. there is no support for using Bicycle polymorphically via pointer/reference to Vehicle), this would effectively be identical to what you want to achieve.
If you do want dynamic polymorphism, you should create a separate, preferably abstract, class, defining the interface for your vehicles, e.g.:
class VehicleInterface
{
public:
// Some pure virtual interface methods
virtual void moveTo(const Vector2 position) = 0;
virtual ~VehicleInterface() = default;
};
And then you can have your concrete vehicles inherit and implement this interface:
class Vehicle : BaseVehicle<VehicleData>, public VehicleInterface
{
public:
virtual void moveTo(const Vector2 position) override
{
// implementation for Vehicle
}
};
class Bicycle : BaseVehicle<BicycleData>, public VehicleInterface
{
public:
virtual void moveTo(const Vector2 position) override
{
// implementation for Bicycle
}
};
Then any function, which would like to work with vehicles polymorphically, can just accept a reference or a pointer to VehicleInterface:
void driveToWork(VehicleInterface* vehicle)
{
vehicle->moveTo(getWorkPosition());
// etc.
}
Short answer; Not in the way that you're aiming for, but you can achieve something similar.
Rather than have an instance declared as you have, if you make data a pointer. You can then have BicycleData inherit VehicleData and then just replace data with the new instance in the constructor of the Bicycle.
ie
class Vehicle {
void PrintData();
protected:
void replaceData(std::shared_ptr<VehicleData> d) {
data = d;
}
std::shared_ptr<VehicleData> getData() {
return data;
}
template<class T>
std::shared_ptr<T> getDataAs() {
return std::dynamic_pointer_cast<T>(data);
}
private:
std::shared_ptr<VehicleData> data;
};
class Bicycle:Vehicle {
Bicycle(){replaceData(std::make_shared<BicycleData>());}
std::shared_ptr<BicycleData> getData() {
return getDataAs<BicycleData>();
}
};
I know this might look like a trivial question, but I haven't found really an elegant C++ solution to the following problem.
I want to represent a complex (tree-like) hierarchy of a "world" of objects. Let's say Animals. Every animal has some basic const properties.
Like for example a name. Then it also has some methods, but they are not significant for this problem.
class Animal {
public:
const char *GetName() const;
protected:
const char *name;
};
class Insect : public Animal {
...
};
class Butterfly : public Insect {
...
};
In this hierarchy I would like to initialize the name in every derived (grand)child. What is an elegant solution to this?
It is also important to say that in this "world" there be only instances of the tree leaves. That is, there will be no objects "Animal" or "Insect". But there will be objects "Butterfly", "Bee" or "Mosquito".
I know the "standard" way to do this is to put name into constructor:
Animal::Animal(const char *name) : name(name) {}
Insect::Insect(const char *name) : Animal(name) {}
Butterfly::Butterfly() : Insect("Butterfly") {}
But if there are more of these properties, the derived classes need also some initialization and the hierarchy has more levels it can become quite a mess:
Animal::Animal(const char *name) : name(name) {}
Vertebrate::Vertebrate(const char *name) : Animal(name) {}
Mammals::Mammals(const char *name) : Vertebrate(name) {}
Ungulate::Ungulate(const char *name) : Mammals(name) {}
Horse::Horse() : Ungulate("Horse") {}
Another option I can see is to drop the const and assign directly in the grandchild's constructor:
class Animal {
public:
const char *GetName() const;
protected:
std::string name;
};
Horse::Horse() {this->name = "Horse";}
But that is also not optimal, because the const is lost and it is more prone to errors (the initialization can be forgotten).
Is there some better way to do this?
Hm - hope that I get not locked out from SO for that answer, but you could use a virtual base class that implements the name-property. Thereby, you will not have to propagate initialization in a base class all way through the hierarchy but could directly address the "very base" constructor with the name-property. Furthermore, you will actually be enforced to call it in any "Grandchild"-class, so you can't forget it by accident:
class NamedItem {
public:
NamedItem(const char* _name) : name(_name) {}
const char *GetName() const;
protected:
const char *name;
};
class Animal : public virtual NamedItem {
public:
Animal(int mySpecificOne) : NamedItem("") {}
};
class Insect : public Animal {
public:
Insect(int mySpecificOne) : Animal(mySpecificOne), NamedItem("") {}
};
class Butterfly : public Insect {
};
The elegant solution is to pass arguments through initialisation. For example, if the "name" variable was the name of the Butterfly (such as "sally" or "david") then it would be obvious it has to be done through initialisation. If you are finding that is ugly, as it is here, it may indicate that your data decomposition/class heirarchy are at fault. In your example every Butterfly object would have an identical set of properties that really refer to their class rather than each instance, ie they are class variables not instance variables. This implies that the "Butterfly" class should have a static pointer to a common "Insect_Impl" object (which might have a pointer to a single "Animal_Impl" object etc) or a set of overridden virtual functions. (Below I only show one level of heirarchy but you should be able to work out more levels)
// Make virtual inherited functionality pure virtual
class Animal {
private:
std::string objName; // Per object instance data
public:
virtual ~Animal(std::string n): objName(n) {}
virtual std::string const& getName() = 0; // Per sub-class data access
virtual std::string const& getOrder() = 0; // Per sub-class data access
std::string const& getObjName() { return this->objName; }
};
// Put common data into a non-inherited class
class Animal_Impl{
private:
std::string name;
public:
Animal_Impl(std::string n): name(n);
std::string const& getName() const { return this->name; }
};
// Inherit for per-instance functionality, containment for per-class data.
class Butterfly: public Animal{
private:
static std::unique< Animal_Impl > insect; // sub-class data
public:
Butterfly(std::string n): Animal(n) {}
virtual ~Butterfly() {}
virtual std::string const& getName() override {
return this->insect->getName(); }
virtual std::string const& getOrder() override {
static std::string order( "Lepidoptera" );
return order; }
};
// Class specific data is now initialised once in an implementation file.
std::unique< Animal_Impl > Butterfly::insect( new Animal_Impl("Butterfly") );
Now using the Butterfly class only needs per-instance data.
Butterfly b( "sally" );
std::cout << b.getName() << " (Order " << b.getOrder()
<< ") is called " << b.getObjName() << "\n";
The issue with your alternative, or any alternative leaving name non-const and protected, is that there is no guarantee that this property is going to be setup properly by the subclasses.
What does the following class give you ?
class Animal {
public:
Animal(const char* something)
const char *GetName() const;
private:
const char *name;
};
The guarantee of the immutability of the Animal interface, which can be a big plus when doing multithreading. If an object is immutable, multiple threads can use it without being a critical resource.
I know the "standard" way to do this is to put name into constructor:
... But if there are more of these properties, the derived classes
need also some initialisation and the hierarchy has more levels it can
become quite a mess
It is not messy at all. Given that there is only one place where the members of object A are being initialised, and it is within the constructor of their subclasses.
I'm doing a Systems Programming homework.
I have to implement a university.
I have a Course class, with child classes ComputerScience courses class, PG courses class, and Elective courses class.
class Course
{
public:
virtual void teach();
virtual void reg(Student &s)=0;
std::string getName();
std::string getDepartment();
int getSemester();
int getMinGrade();
void addStudent(Student *s);
void removeStudent(Student *s);
protected:
std::string _department;
std::string _name;
int _semester;
int _minGrade;
std::vector<Student*> studentsList;
};
class CSCourse : public Course
{
public:
CSCourse();
CSCourse(std::string department, std::string name, int semester, int mingrade);
~CSCourse();
std::string getName();
std::string getDepartment();
int getSemester();
int getMinGrade();
void addStudent(Student *s);
void removeStudent(Student *s);
};
(PG courses and Elective courses child classes are the same)
In the functions in the Course class (which are not void, like getSemester and such..) I just do dynamic_cast to figure what type of course is it.
I am having this problem:
coursesVector is:
std::vector<Course*> coursesVector
and dp variable is a string containing either CS, PG or Elective. In the main, I do this:
if (dp == "CS")
{
CSCourse *csCourse = new CSCourse(dp, name, semester, minGrade);
coursesVector.push_back(csCourse);
}
it gives me "Cannot allocate object of abstract type CS Course".
Same goes for PG and Elective!
But, in my definiton of hte class, CS course is not abstract!
The CSCourse class is abstract.
You have declared a pure virtual function reg in Course, but not provided an implementation in CSCourse.
You compiler undoubtedly told you exactly this as well.
You're inheriting from an abstract class which is fine, but you are never implementing the pure virtual function that the base class defines.
Also you need a virtual destructor in your base class;)
Edit:
You're also doing other things that probably aren't necessary like redeclaring most of your derived class functions. I bet their implementation is the exact same as your base class?
You have not implemented the pure virtual function reg in your derived class:
virtual void reg(Student &s)=0;
So yes, your class is abstract.