Access methods from derived class using an object from base class - c++

I need to solve this problem about classes in C++. The problem says I need to create a base class, which has to be derived into 3 other derived classes. On main, I created a vector that can save objects from the base class to save the 3 different derived classes. The thing is that I don't know how to access the methods of the derivative classes when I access the vectors. For example, class C has 2 attributes and methods that base and other classes don't have, I need to have some way to access those methods using the vector of the base class. I hope someone could help me.
#include <iostream>
#include <vector>
#include <ctime>
using namespace std;
class Base{
protected:
string placa;
int ano_de_registro;
public:
Base(){};
Base(string _placa, int _ano_de_registro):placa(_placa),ano_de_registro(_ano_de_registro){};
const string &getPlaca() const {
return placa;
}
int getAnoDeRegistro() const {
return ano_de_registro;
}
};
class A: public Base{
int cubicaje;
int caballos_de_fuerza;
int contaminacion;//0==minimo, 1==normal y 2==excesivo
public:
A(){};
A(string _placa, int _ano_de_registro, int _cubicaje, int _caballos_de_fuerza, int _contaminacion):Base(_placa,_ano_de_registro),cubicaje(_cubicaje),caballos_de_fuerza(_caballos_de_fuerza),contaminacion(_contaminacion){};
int getCubicaje() {
return cubicaje;
}
int getCaballosDeFuerza() {
return caballos_de_fuerza;
}
int getContaminacion() {
return contaminacion;
}
};
class B: public Base{
int cubicaje;
public:
B(){};
B(string _placa, int _ano_de_registro, int _cubicaje):Base(_placa,_ano_de_registro),cubicaje(_cubicaje){};
int getCubicaje() const {
return cubicaje;
}
};
class C: public Base{
int cantidad_de_ejes;
int sobregarga;
public:
C(){};
C(string _placa, int _ano_de_registro,int _cantidad_de_ejes, int _sobregarga):C(_placa,_ano_de_registro),cantidad_de_ejes(_cantidad_de_ejes),sobregarga(_sobregarga){};
int getCantidadDeEjes() {
return cantidad_de_ejes;
}
** int getSobregarga() const {
return sobregarga;
}**
};
int main() {
srand(time(NULL));
int a1,c1,c2,sc,cb,ct,cde, r1, vs;
vector<string> Placas={"A1R 112","F5U-597","A1A-004","D5B-193","EUA-123","A8D-457","FCD-784","F0X-694","SLA-249","EBD-608",};
vector<Base*> Vehiculos;
for (int i=0;i<10;i++){
r1=rand()%3;
vs=rand()%Placas.size();
a1=rand()%22+2000;
c1=rand()%10;
c2=rand()%10;
cb=rand()%10;
ct=rand()%3;
cde=rand()%4+3;
sc=rand()%10;
A* carro=new A(Placas.at(vs),a1,c1,cb,ct);
Vehiculos.push_back(carro);
B* moto=new B(Placas.at(vs),a1,c2);
Vehiculos.push_back(moto);
** C* camion=new C(Placas.at(vs),a1,cde,sc);
Vehiculos.push_back(camion);**
}
**Vehiculos.at(0)->getSobrecarga;**
return 0;
}
Bold parts are the vector trying to access that method, the method itself and how I create the object using dynamic objects

Note: it is usually better to expand the base class with virtual functions so that no one needs to know exactly what type is being referenced. If the children are so different that a common interface is not possible, inheritance is probably not the right solution.
If you're being forced to do this for a course, there are two changes you need to make. The base class needs to have virtual methods to be polymorphic. It just so happens it needs a virtual destructor in order for the derived classes to be destroyed correctly from a reference to Base.
class Base
{
protected:
string placa;
int ano_de_registro;
public:
Base()
{
}
Base(string _placa, int _ano_de_registro) :
placa(_placa), ano_de_registro(_ano_de_registro)
{
}
virtual ~Base() = default; //Addition
const string& getPlaca() const
{
return placa;
}
int getAnoDeRegistro() const
{
return ano_de_registro;
}
};
The second change is using dynamic_cast.
Vehiculos.at(0)->getSobrecarga;
becomes (I've also corrected a few omissions)
C* example = dynamic_cast<C*>(Vehiculos.at(2)); // get a C from the vector
if (example) // test for non-null to make sure we did indeed get a C
{
example->getSobregarga(); // do the deed.
}

Related

Is it a necessary trade-off that using smart pointers requires my class to be publicly instantiable?

I have a base product class with a few private members and a public getter that derived classes inherit. I would like to disqualify instantiation, since the class is intended for use with an abstract factory. I thought protected con/destructors might work, however, this breaks my smart pointers. Friending seems like a useful disaster. Is there a well-known solution to this, or should I resign myself to the fact that any client who has the factory injected must also know enough to instantiate the base product?
class Product
{
private:
char type_name;
char size_name;
public:
Product(char, char);
virtual ~Product() {}
void Print();
};
Use a token key.
private:
Product(char, char);
struct key_t{explicit key_t(int){}};
static key_t key(){return key_t(0);}
public:
Product(key_t, char a, char b):Product(a,b){}
static std::shared_ptr<Product> make_shared(char a, char b){ return std::make_shared<Product>(key(),a,b); }
anyone with a Product::key_t can construct a Product without being a friend. And without the key, you cannot.
This lets Product pass creation-rights as a value.
Smart pointers with configurable destroy code can use similar techniques. But I'd just make the destructor public.
Your static member function, or friend function, which is the factory should have no problem with calling protected constructors and returning a smart pointer. Generally plan to return a std::unique_ptr<BaseClass> which can be converted into a std::shared_ptr if the caller wants that instead.
Make the virtual destructor public.
Update: Don't bother making the factory a friend. You only need to prevent the construction of the base and intermediate classes. Make them effectively hidden and private by hiding the implementation classes in their own source file. Or an anonymous namespace I suppose.
Here have some code of how I would do it:
#include <iostream>
#include <memory>
#include <string>
// ITest is the only class any other code file should ever see.
class ITest {
protected:
ITest() = default;
public:
virtual ~ITest() = 0;
virtual int getX() const = 0;
virtual int getY() const = 0;
};
// Destructors must always have an implementation even if they are pure virtual.
ITest::~ITest() {}
std::ostream &operator<<(std::ostream &os, const ITest &x) {
return os << '[' << x.getX() << ',' << x.getY() << ']';
}
// Declaration of constructTest factory function.
// Its definition should be hidden in a cpp file.
std::unique_ptr<ITest> constructTest(int x);
// The main function does not need to know anything except the ITest interface
// class and the constructTest function declaration.
int main(int argc, char *argv[]) {
int val = 0;
if (argc > 1)
val = std::stoi(argv[1]);
auto p = constructTest(val);
std::cout << *p << std::endl;
}
// These classes should be defined in a private header file or in a cpp file.
// Should not be visible to any other code. It has no business knowing.
// Hiding all of this implementation is sort of the point of abstract interface
// classes and factory function declarations.
class TestBase : public ITest {
private:
int x = 0;
int y = 0;
protected:
TestBase(int x = 0, int y = 0) : x(x), y(y){};
public:
int getX() const override { return x; }
int getY() const override { return y; }
};
class TestA final : public TestBase {
public:
TestA() = default;
};
class TestB final : public TestBase {
public:
TestB(int x, int y) : TestBase(x, y) {}
int getX() const override { return -TestBase::getX(); }
};
std::unique_ptr<ITest> constructTest(int x) {
// make_unique is c++14.
// For C++11 use std::unique_ptr<ITest>(new TestB(x, x)
if (x) {
return std::make_unique<TestB>(x, x);
// return std::unique_ptr<ITest>(new TestB(x, x));
}
return std::make_unique<TestA>();
}
The answer was to make the destructor a pure virtual AND to implement it with an empty body. That empty implementation is where I got tripped up. Print() doesn't need to be static.
Product.hpp
#include <memory>
class Product {
public:
virtual ~Product() = 0;
void Print();
protected:
char type_name{};
char size_name{};
private:
};
Product.cpp
#include "Product.hpp"
Product::~Product() {}
void Product::Print() {
//Print p
}

how to pass subclass as parameter for function expecting base class then pass that object into vector of pointers to those abstract class objects?

TL;DR
I am trying to pass a subclass into a function that expects the subclass's base class and then store a unique pointer of that base class in a vector in a third, completely separate class.
(C++ 11 and higher)
End TL;DR
I have 3 classes total and then my int main().
The base (abstract) class has a constructor and a virtual function.
The base class constructor is implemented, the virtual function is not.
The second class is the subclass to the base class.
It implements its own constructor and calls the base constructor.
The second part of the sub class is the concrete implementation of the virtual base class function.
I then have a third class that has its own constructor.
This third class has a function whose function header contains a reference to the base class.
This same function then tries to pass this reference to the abstract class and then .push_back() the reference into a vector of std::unique_ptr of this abstract class.
(Because I cannot directly have a vector of abstract class instances.)
My issue is that I am currently unable to get a version of this code to compile.
I have been referencing some resources online to try to solve my problem.
pass unique_ptr as an object
https://stackoverflow.com/questions/8114276/how-do-i-pass-a-unique-ptr-argument-to-a-constructor-or-a-function
adding elements of a vector of a base class
https://stackoverflow.com/questions/31410858/adding-elements-to-stdvector-of-an-abstract-class
can't access derived class method from pointer of base class - not entirely relavent, but good knowledge
https://stackoverflow.com/questions/23489554/cant-access-derived-class-method-from-pointer-of-type-base-class
I have created a shortened version of this problem in an example C++ executable that does not compile.
Here is the file:
/*
This script demonstrates my dilemma of trying to pass a subclass object
as a parameter to a function that expects the base class, and then
take that passed in object in the function and add it to a vector of that object
in a completely different class.
*/
#include <iostream>
#include <memory>
#include <vector>
class Baseclass
{
public:
Baseclass(int i)
{
lala = i;
}
// subclass MUST implement this method.
virtual int addme(int d) = 0;
protected:
int lala;
};
class Subclass : Baseclass
{
public:
Subclass(int d, int l) : Baseclass(d)
{
blahblah = l;
}
int addme(int d)
{
return blahblah + lala + d;
}
protected:
int blahblah;
};
class Mainclass
{
public:
Mainclass(uint blah)
{
anotherone = blah;
}
// This is the function I cannot seem to get to work.
// How can I make the function parameter an abstract class?
// The object being passed in is NOT abstract...
bool addController(Baseclass & basecont)
{
// This line here does NOT compile!!
// controllers.push_back(std::make_unique<What goes here?>(basecont));
return true;
}
protected:
uint anotherone;
std::vector<std::unique_ptr<Baseclass>> controllers;
};
int main(int argc , char ** argv)
{
// create subclassed controllers
Subclass cont1 = Subclass(12, 23);
Subclass cont2 = Subclass(233, 2);
// create main object
Mainclass mainbro = Mainclass(23);
// Add the subclased controllers to the main class
// THESE 2 lines do not compile!!
// mainbro.addController(cont1);
// mainbro.addController(cont2);
//
return 0;
}
I figure that I am doing something very wrong, but I do not feel the process I outlined in itself is impossible. I just think that I am going about the problem wrong.
I have highlighted, in the script, where I am not sure what I should do and where the code breaks.
I may need to take an alternative approach to the problem, I just do not know what alternatives I have available.
I see different way to fix your code, with different meaning.
Store pointers (main has ownership of the objects)
class Mainclass
{
public:
void addController(Baseclass& basecont)
{
controllers.push_back(&basecont);
}
protected:
std::vector<Baseclass*> controllers;
};
Transfer ownership
class Mainclass
{
public:
void addController(std::unique_ptr<Baseclass> basecont)
{
controllers.push_back(std::move(basecont));
}
protected:
std::vector<std::unique_ptr<Baseclass>> controllers;
};
with main:
int main()
{
auto cont1 = std::make_unique<Subclass>(12, 23);
auto cont2 = std::make_unique<Subclass>(233, 2);
Mainclass mainbro(23);
mainbro.addController(std::move(cont1));
mainbro.addController(std::move(cont2));
}
Store copies
class Mainclass
{
public:
void addController(Baseclass& basecont)
{
controllers.push_back(basecont.clone());
}
protected:
std::vector<std::unique_ptr<Baseclass>> controllers;
};
With
class Baseclass
{
// ...
public:
virtual int addme(int d) = 0;
virtual std::unique_ptr<Baseclass> clone() = 0;
};
class Subclass : Baseclass
{
// ...
public:
std::unique_ptr<Baseclass> clone() override { return std::make_unique<Subclass>(*this); }
};
Whenever you use base pointers or references with virtual methods, always add a virtual destructor:
virtual ~Baseclass() = default;
This prevents undefined behavior when the base pointers get deleted.
Next bit, use public inheritance to allow the compiler to implicitly upcast from unique_ptr<Subclass> to unique_ptr<Baseclass>:
class Subclass : public Baseclass
Your last issue is one of ownership. By having a vector of unique_ptr, you are saying that your class owns all those objects. But by declaring them on the stack in main you are saying that main owns them. Instead, use make_unique in the main routine, and transfer ownership with std::move:
bool addController(std::unique_ptr<Baseclass> basecont)
{
controllers.push_back(std::move(basecont));
return true;
}
...
auto cont1 = std::make_unique<Subclass>(12, 23);
auto cont2 = std::make_unique<Subclass>(233, 2);
// create main object
Mainclass mainbro = Mainclass(23);
mainbro.addController(std::move(cont1));
mainbro.addController(std::move(cont2));
All together:
#include <iostream>
#include <memory>
#include <vector>
class Baseclass
{
public:
Baseclass(int i)
{
lala = i;
}
virtual ~Baseclass() = default;
// subclass MUST implement this method.
virtual int addme(int d) = 0;
protected:
int lala;
};
class Subclass : public Baseclass
{
public:
Subclass(int d, int l) : Baseclass(d)
{
blahblah = l;
}
int addme(int d)
{
return blahblah + lala + d;
}
protected:
int blahblah;
};
class Mainclass
{
public:
Mainclass(uint blah)
{
anotherone = blah;
}
bool addController(std::unique_ptr<Baseclass> basecont)
{
controllers.push_back(std::move(basecont));
return true;
}
protected:
uint anotherone;
std::vector<std::unique_ptr<Baseclass>> controllers;
};
int main(int argc , char ** argv)
{
// create subclassed controllers
auto cont1 = std::make_unique<Subclass>(12, 23);
auto cont2 = std::make_unique<Subclass>(233, 2);
// create main object
Mainclass mainbro = Mainclass(23);
mainbro.addController(std::move(cont1));
mainbro.addController(std::move(cont2));
return 0;
}
Demo: https://godbolt.org/z/EyQD6S
#include <iostream>
#include <memory>
#include <vector>
class Baseclass
{
public:
Baseclass(int i)
{
lala = i;
}
// subclass MUST implement this method.
virtual int addme(int d) = 0;
protected:
int lala;
};
class Subclass : public Baseclass
{
public:
Subclass(int d, int l) : Baseclass(d)
{
blahblah = l;
}
int addme(int d)
{
return blahblah + lala + d;
}
protected:
int blahblah;
};
class Mainclass
{
public:
Mainclass(uint blah)
{
anotherone = blah;
}
// you need to make the function a template, otherwise
// you'll slice the top off the SubClass, and incorrectly
// make a copy of the base class (which you can't do,
// because BaseClass is pure virtual)
template<typename T>
bool addController(T& basecont)
{
// dont push_back new unique_ptrs, emplace_back instead!
controllers.emplace_back(new T(basecont));
return true;
}
protected:
uint anotherone;
std::vector<std::unique_ptr<Baseclass>> controllers;
};
int main(int argc , char ** argv)
{
// create subclassed controllers
Subclass cont1 = Subclass(12, 23);
Subclass cont2 = Subclass(233, 2);
// create main object
Mainclass mainbro = Mainclass(23);
// It's worth pointing out that these methods will take new copies of
// cont1 and cont2 (we don't want the mainbro instance to delete the
// memory for cont1 and cont2, since they are stack allocated)
mainbro.addController(cont1);
mainbro.addController(cont2);
//
return 0;
}

virtual public inheritance? Need help understanding code

I have question about virtual inheritance.
I'm interested why this code prints 1000 (from class "two") and not 3 (from class "one")
here's the code:
#include <iostream>
using namespace std;
class A {
protected:
int number;
public:
A (int a=0) {number=a;}
};
class one:virtual public A {
public:
one (int a=3) {number=a;}
void print() {cout<<number<<endl;}
};
class two :virtual public A {
public:
two (int a=1000) {number =a;}
void print() { cout<<number<<endl; }
};
class B:public one,public two {
public:
void print() { cout<<number<<endl; }
};
int main () {
B A;
A.print();
}
The base classes are initialised in the order they are declared: one then two. The virtual inheritance means that they both share the same instance of A, so there is only one variable called number here.
Initialising one assigns 3 to number then initialising two assigns 1000 to it. So, after initialising the whole object, it ends up with the value 1000.

Problematic design modifiying/accessing information of a derived class using the base object

My problem is the following:
int main()
{
Base* derivedobject = new Derived1();
derivedobject->GetProperties()-> ???
return 0;
}
//********************
// BaseClass.h
//********************
struct PropertyStruct
{
int x;
};
class Base
{
public:
Base();
~Base();
virtual PropertyStruct GetProperties() = 0;
private:
};
//********************
// DerivedClass1.h
//********************
struct PropertyStruct
{
int y;
};
class Derived1 : public Base
{
public:
Derived1();
~Derived1();
PropertyStruct GetProperties() { return myOwnDifferentProperties; };
private:
};
//********************
// DerivedClass2.h
//********************
struct PropertyStruct
{
float z;
};
class Derived2 : public Base
{
public:
Derived2();
~Derived2();
PropertyStruct GetProperties() { return myOwnDifferentProperties };
private:
};
If I do it like that I'm going to get an error saying that PropertyStruct is a redefinition. If I use a namespace or rename the struct inside the derived class I am then going to get an error telling me that the return type is not the same as defined by Base.
If I define the virtual functions return type as a pointer it compiles, though the next problem when accessing the function "GetProperties" from the main method (in this example) the base object does not know what variables are inside the struct of the derived class.
Is there any way I can realize this ?
That I can get the different properties of each derived object but using the base class object ?
As others have mentioned, there are ways to achieve your goals here but ultimately you will find yourself writing code like the following:
Base * object = ...;
if object is Derived1 then
get Property1 and do something with it
else if object is Derived2 then
get Property2 and do something with it
This is an anti-pattern in object-oriented programming. You already have a class hierarchy to represent the differences between the various derived types. Rather than extracting the data from your objects and processing it externally, consider adding a virtual function to the base class and letting the derived classes do the processing.
class Base
{
public:
virtual void DoSomething() = 0;
};
class Derived1 : Base
{
public:
void DoSomething()
{
// use myOwnDifferentProperties as necessary
}
private:
PropertyStruct myOwnDifferentProperties;
};
If it's not appropriate to put the required processing in the derived classes (i.e. if it would introduce unwanted responsibilities) then you may want to consider the Visitor Pattern as a way to extend the functionality of your hierarchy.
Since template functions cannot be virtual you can use hierarchy of your properties. It's only one way, no other ways. For get elements of derived Properties you should use virtual getter functions.
struct BaseProp
{
virtual ~BaseProp() { }
virtual boost::any getProperty() const = 0;
};
struct PropertyStruct : BaseProp
{
boost::any getProperty() const { return x; }
private:
int x;
};
struct PropertyStruct2 : BaseProp
{
boost::any getProperty() const { return y; }
private:
float y;
};
class Base
{
public:
virtual std::shared_ptr<BaseProp> GetProperties() const = 0;
virtual ~Base() { }
}
class Derived
{
public:
std::shared_ptr<BaseProp> GetProperties() const { return new PropertyStruct(); }
};
class Derived2
{
public:
std::shared_ptr<BaseProp> GetProperties() const { return new PropertyStruct2(); }
};
You can use template class to do that:
struct PropertyStruct1 {
float f;
};
struct PropertyStruct2 {
int i;
};
template<class T>
class A{
public:
T GetProperties() {return mProps;}
private:
T mProps;
};
int main (int argc, const char * argv[]) {
A<PropertyStruct1> a1;
int f = a1.GetProperties().f;
A<PropertyStruct2> a2;
int i = a2.GetProperties().i;
return 0;
}

exporting class from dll error

I want to expose only the CreateSort() for the client. it was to create an object for the implementation of the sort class i.e imSort then return it to the client.but the compiler says that it cannot create an object of an abstract class eventhough all the functions have been defined in the derived class.
/////sort.h
class __declspec(dllexport) Sort {
public:
virtual int* BSort() const=0;
virtual void getdata() const=0;
};
extern "C" Sort *CreateSort();
/////imSort.h
#include "Sort.h"
class imSort : public Sort{
private:
int i,j,num;
int temp;
int *a;
public:
imSort();
int* BSort();
void getdata();
}
/////imSort.cpp
#include <iostream>
#include "imSort.h"
Sort *CreateSort()
{
return new imSort(); /* object of abstract class type "imSort" is not allowed: */
}
imSort::imSort()
{
i=j=num=0;
*a=0;
}
void imSort::getdata()
{
std::cout<<"\nEnter the number of elements..";
std::cin>>num;
for(i=0;i<num;i++)
{
std::cin>>*a;
*(a++);
}
}
int* imSort::BSort()
{
for(i=0;i<num;i++)
for(j=i+1;j<num;j++)
{
if(*(a+i)<*(a+j))
{
temp=*(a+i);
*(a+i)=*(a+j);
*(a+j)=temp;
}
}
return a;
}
Your base class has:
virtual int* BSort() const=0;
virtual void getdata() const=0;
But your derived class has:
int* BSort();
void getdata();
Repeating the virtual keyword is optional, but without the const these are separate functions, unrelated to the virtual base functions.
As a result, those pure virtual functions remain un-overridden in the derived class, and so imSort (silly name for a type if you ask me) is still abstract.
Your fixed derived class definition is thus:
class imSort : public Sort {
private:
int i, j, num;
int temp;
int* a;
public:
imSort();
int* BSort() const; // <--- const
void getdata() const; // <--- const
}; // <--- ;
(Notice how indentation improves the legibility of your code? And you forgot the ; at the end of your class definition.)
Please write a fully-formed question next time, and reduce your problem to a minimal testcase.
If the virtual functions in the abstract Sort class are declared const, so should the implementations in the imSort class, but they are not.
So just add const here and there...