How can I implement a vector<class> template's function? - c++

I want to implement a template like this,
class animal{
}
class beast : public animal {
public:
beast(string name){}
void cry(){
cout<<"kuuuuu"<<endl;
}
}
int main(){
vector<animal*> a;
a.push_back(beast("tiger"))
vector[0].cry();
}
I want to implement similar to it. But my visualstudio cannot find the cry() function.
Please, how can I do it?

animal does not have a cry method. So you cannot call a cry on animal.
Also you have numerous syntax errors, which should give you errors before this line:
Your vector contains pointers and you are trying to stuff object itself inside.
To access member of object pointer points to, you should use ->, not ..

A lot of changes needed.static_cast is essential to call your cry method.
class definition should end with ;
Since you created vector<animal*>, you need to new the object before push back.
When you invoke the function cry , you need to static_cast it back to beast* and use -> instead . to invoke the cry function.
class animal{
};
class beast : public animal {
public:
beast(std::string name){}
void cry(){
std::cout<<"kuuuuu"<<std::endl;
}
};
int main(){
std::vector<animal*> a;
a.push_back(new beast("tiger"));
(static_cast<beast*>(a[0]))->cry();
}

#include <vector>
#include <iostream>
#include <string>
using namespace std;
class animal {
public:
virtual void cry() = 0; // declare public virtual cry method
};
class beast : public animal {
public:
beast(string name) {
}
void cry() {
cout << "kuuuuu" << endl;
}
};
int main() {
vector<animal*> a;
a.push_back(new beast("tiger")); // create new object and end with semicolon
a[0]->cry(); // use -> instead of . to call cry method of beast object pointed at
}

Related

C++ Inheritance (instantiating derived class inside base class)

class MainClass
{
string _ClassName;
public:
string MainClass(string _C)
{
_ClassName = _C;
}
SubClass s1;
};
class SubClass : public MainClass
{
public:
string Method_1()
{
return a;
}
string Method_2()
{
return a;
}
};
Why is SubClass s1 not working can someone tell me please what am i missing I'm new to OOP.
I want to instantiate SubClass object inside MainClass but it doesn't seems to work.
basically, my aim is to access SubClass functions when MainClass object is instantiated in Main method something like this:
int Main()
{
MainClass M1("test");
M1.s1.Method_1(); <--------- this
}
The first problem is, that the MainClass does not know a thing about SubClass when you're trying to instantiate the object.
You need to use a forward declaration and a pointer to make it work.
Header file:
class SubClass; //Forward declaration, allows pointer.
class MainClass
{
string _ClassName;
public:
MainClass(string _C); //No return type on constructor
~MainClass();
SubClass *s1; //Size: 4 Bytes on 32bit system
protected:
MainClass();
};
class SubClass : public MainClass
{
public:
string Method_1();
string Method_2();
};
CPP file:
#include "headerFile.h"
MainClass::MainClass(string _C) :
_ClassName(_C),
s1(new SubClass) //Class definition is now known.
{
}
MainClass::MainClass() : s1(nullptr) //Nullptr -> No new object, no infinite recursion.
{
}
MainClass::~MainClass()
{
delete s1; //Do not forget to clean up your pointer.
}
string SubClass::Method_1()
{
return "a";
}
string SubClass::Method_2()
{
return "a";
}
Call:
int main()
{
MainClass M1("test");
M1.s1->Method_1(); //-> to dereference the pointer.
}
The second problem, as Richard Critten has pointed out, is an infinite recursion, which will cause your program to crash very quickly.
Each time you instantiate a SubClass, you also create a subclass, which creates yet another MainClass etc.
To circumvent this, you'll need a protected constructor, which does NOT create the subclass member.
The third problem:
You are returning a in your methods, which suggests a variable.
If you meant to return 'a', you need to put them into quotation marks.
Finally, in order to get it to compile, you'll need to write Main with a small m (int main()), otherwise the linker will complain.
However, as Mr. 'Not a number' correctly stated, the above edits only make your code compile.
What you likely are actually after however would be using virtual functions, which can be overridden by sub classes to specialize the behavior.
An example code using actual inheritance:
Header file:
class MainClass
{
string _ClassName;
public:
MainClass(string _C); //No return type on constructor
virtual ~MainClass(); //All base classes that have at least one virtual method should also have a virtual destructor, even if it is empty.
virtual void doSomething();
};
class SubClass : public MainClass
{
public:
SubClass(string className);
void doSomething();
};
CPP file:
#include "headerFile.h"
#include <stdio.h>
MainClass::MainClass(string _C) : _ClassName(_C)
{
}
MainClass::~MainClass()
{}
void MainClass::doSomething()
{
printf("Called from MainClass\n");
}
SubClass::SubClass(string className) : MainClass(className)
{
}
void SubClass::doSomething()
{
printf("Called from SubClass\n");
}
Call:
int main()
{
MainClass M1("test");
SubClass sub("SubClass");
MainClass *pointer = ⊂
M1.doSomething(); //Outputs 'Called from MainClass'.
sub.doSomething(); //Outputs 'Called from SubClass'.
pointer->doSomething(); //Also outputs 'Called from SubClass', since it points to sub and because sub overrides the behaviour from MainClass.
}
To call the parent method from the child method, you need to invoke the method from within the override with the parent class.
Example (in SubClass::doSomething): MainClass::doSomething().

How to write overloaded functions for derived classes that are stored in a std::vector as the base class

Been experimenting and searching for how to do this and would like some help....
Goal : Have a std::vector store either Cat and Bear objects (like a heterogenous container).
Then iterate the vector and perform an overloaded function A or function B depending on type (Cat/Bear)
Solution : I created a base class (Animal), the std::vector stores shared_ptrs of this type.
I create Animal derived Cat or Bear objects (new), cast their pointers to shared_ptr<Animal> and push to vector.
Problem : I have two processing functions that take Cat or Bear parameters respectively. But I need to std::static_pointer_cast<Bear> or std::static_pointer_cast<Cat> the Animal pointers from the vector before passing to the function. I want the correct function to be called automatically (due to overloading).
thanks
class AnimalClass
{
AnimalType type;
};
class Bear : public AnimalClass
{
}
class Cat : public AnimalClass
{
}
void action(Bear* bear)
{
run();
}
void action(Cat* cat)
{
stroke();
}
int main()
{
std::vector<shared_ptr<AnimalClass>> store;
// Populate store
Cat* cat= new Cat();
store.push_back(shared_ptr<AnimalClass>)cat );
Bear* bear= new Bear();
store.push_back(shared_ptr<AnimalClass>)bear );
// Process store
for (auto item : store)
{
action(item); // Does not compile unless item is static_pointer_cast to Bear or Cat, don't want to do that.
}
}
The idiomatic solution ist to use the virtual dispatch that C++ already offers out of the box. You need to turn the so far free functions into virtual member functions and override them in derived classes. Example:
#include <cstdio>
struct Animal
{
virtual void action() = 0;
};
struct Cat : Animal {
void action() override
{
std::puts("Cat::action");
}
};
struct Bear : Animal {
void action() override
{
std::puts("Bear::action");
}
};
You can use these as depicted in the following.
std::vector<std::shared_ptr<Animal>> store;
store.push_back(std::make_shared<Cat>());
store.push_back(std::make_shared<Bear>());
for (auto& item : store)
item->action();
Note that I have used std::make_shared in favor of a raw new. And note that all classes are structs at this point to avoid typing public too often.
As alternative to traditional virtual method way, you might use std::variant:
struct Bear
{
void run() { std::cout << "run\n"; }
};
struct Cat
{
void stroke() { std::cout << "stroke\n"; }
};
void action(Bear& bear)
{
bear.run();
}
void action(Cat& cat)
{
cat.stroke();
}
using Animal = std::variant<Cat, Bear>;
int main()
{
std::vector<Animal> store{Cat{}, Bear{}};
// Process store
for (auto& animal : store)
{
std::visit([](auto& animal){ action(animal); }, animal);
}
}
Demo

task list in C++ (vector with more than one type)

My aim is to fill a list of task; each will be an object containing the description of the task. Let'say there will be only two type of tasks : file copy and repertory copy.
Since a vector cannot contain more than one type of objects, I though to create a generic task class and two classes that inheritate from that one.
Here is the code :
#include <iostream>
#include <deque>
#include <string>
using namespace std;
class GenericTask{
public :
string config;
GenericTask(string s){
config=s;
}
void run(){
cout<<"Running generic task" <<endl;
}
};
class FileCopyTask : public GenericTask{
public:
string filename;
FileCopyTask(string cf,string fn):GenericTask(cf)
{
filename=fn;
}
void run(){
cout<<"file :"<<filename<<endl;
}
};
class RepertoryCopyTask : public GenericTask{
public:
string repname;
RepertoryCopyTask(string cf,string rn):GenericTask(cf)
{
repname=rn;
}
void run(){
cout<<"repertory : "<<repname<<endl;
}
};
void run_next(deque<GenericTask> &task_list){
task_list.front().run();
task_list.pop_front();
}
int main()
{
RepertoryCopyTask rtask("configuration","/home");
FileCopyTask ftask( "configutation","gile.tex" );
deque<GenericTask> task_list;
task_list.push_back(rtask);
task_list.push_back(ftask);
run_next(task_list);
}
As it, it does not work because run_next expect a GenericTask and both rtask and ftask are treated as generic.
How should I do ?
I already tried to add template here and there, but ultimately it does not work because I need to know the type inside the deque before to "extract" something.
Can I consider this as an answer ?
Why not create objects of FileCopyTask and RepertoryCopyTask and save them as pointers to GenericTask? This way you can leverage the power of runtime polymorphism.
Like this:
int main()
{
std::unique_ptr<GenericTask> ftask = std::make_unique<FileCopyTask>("configutation","gile.tex");
std::unique_ptr<GenericTask> rtask = std::make_unique<FileCopyTask>("configuration","/home");
...
}
void run_next(deque<std::unique_ptr<GenericTask> > &task_list)
{
....
}
Also, do not forget to mark the run() method in class GenericTask as virtual. Also provide a virtual destructor.
I made some changes in your source. Defined your base fn as virtual and stored objects with pointers. You can check it below.
#include <iostream>
#include <deque>
#include <string>
using namespace std;
class GenericTask{
public :
string config;
GenericTask(string s){
config=s;
}
virtual void run(){
cout<<"Running generic task" <<endl;
}
};
class FileCopyTask : public GenericTask{
public:
string filename;
FileCopyTask(string cf,string fn):GenericTask(cf)
{
filename=fn;
}
void run(){
cout<<"file :"<<filename<<endl;
}
};
class RepertoryCopyTask : public GenericTask{
public:
string repname;
RepertoryCopyTask(string cf,string rn):GenericTask(cf)
{
repname=rn;
}
void run(){
cout<<"repertory : "<<repname<<endl;
}
};
void run_next(deque<GenericTask*> &task_list){
task_list.front()->run();
task_list.pop_front();
}
int main()
{
RepertoryCopyTask* rtask = new RepertoryCopyTask("configuration","/home");
FileCopyTask* ftask = new FileCopyTask( "configutation","gile.tex" );
deque<GenericTask*> task_list;
task_list.push_back(ftask);
task_list.push_back(rtask);
run_next(task_list);
}
How should I do ?
Consider these steps:
define GenericTask as a base class (add virtual destructor, make void run virtual)
override the run function in derived classes
store elements in the queue as std::unique_ptr, instead of "by value" to avoid the slicing problem.
I already tried to add template here and there, but ultimately it does not work because I need to know the type inside the deque before to "extract" something.
You can add a boost::variant as the value, allowing the storage of unrelated types.
Can I consider this [this=answer proposing boost::any as value type] as an answer ?
Yes. boost::variant would be similar (the difference is that boost::any supports setting any value; boost::variant only supports values of the types provided as variant arguments).
A classical case of virtual. The run methods need to be declared virtual s.t. you are actually calling RepertoryCopyTask::run() on an object of type GenericTask.
When done correctly,
FileCopyTask t("a", "b");
GenericTask & g = t;
g.run();
will call FileCopyTask::run instead of GenericTask::run (which it would in the original question).
When you did this, you can't store your FileCopyTasks and RepertoryCopyTask in a contaianer for GenericTask. This is because they might even have different size. To get around this, you should store unique_ptrs for them in some container, i.e.
std::vector<std::unique_ptr<GenericTask> > tasks;
This would be the correct way of solving your problem.

C++: Field has incomplete type

I am trying to implement the strategy design pattern as an exercise. My classes are pretty simple:
1) Fly.cpp
class Fly
{
public:
Fly();
bool fly();
};
class CanFly : public Fly
{
public:
bool fly()
{
return true;
}
};
class CantFly : public Fly
{
public:
bool fly()
{
return false;
}
};
2) Animal.cpp
class Fly;
class Animal
{
Fly myFly;
public:
Animal(Fly f);
void setFly(Fly f);
Fly getFly();
};
Animal::Animal(Fly f)
{
myFly = f;
}
void Animal::setFly(Fly f)
{
myFly = f;
}
Fly Animal::getFly()
{
return myFly;
}
3) Dog.cpp
#include <iostream>
using namespace std;
class Animal;
class Dog : public Animal
{
public:
Dog(Fly f);
};
Dog::Dog(Fly f)
{
setFly(f);
cout << "Dog : " << getFly().fly() << endl;
}
4) Bird.cpp
#include <iostream>
using namespace std;
class Animal;
class Bird : public Animal
{
public:
Bird(Fly f);
};
Bird::Bird(Fly f)
{
setFly(f);
cout << "Bird : " << getFly().fly() << endl;
}
5) AnimalTest.cpp
#include <iostream>
using namespace std;
class Dog;
class Bird;
class CanFly;
class CantFly;
int main()
{
Fly f1 = new CanFly();
Fly f2 = new CantFly();
Bird b(f1);
Dog d(f2);
return 0;
}
The error which I get upon building the code is :
Animal.cpp:5:6: error: field 'myFly' has incomplete type 'Fly'
Fly myFly;
^
Can anyone help me why?
Thanks
Incomplete type error means that compiler doesn't see definition of the class, only declaration.
If you create an object or if you pass an object by value then you need to provide a definition of the class to the compiler. You do create objects and pass them around by values hence you need to include definition of relevant classes you pass into cpp files.
But that is not what you really want to do.
Your intention is to employ polymorphism so you need to pass objects by reference or by pointer instead.
Your Animal class should be:
class Animal
{
Fly &myFly;
public:
Animal(Fly &f);
void setFly(Fly &f);
Fly const &getFly();
};
That way you can pass any of Fly, CanFly, or CantFly objects into Animal object.
You also need to reorganise your code. You need to separate class definitions into header files. For example:
//Animal.h
class Fly; <=== Declaration. OK here.
class Animal
{
Fly &myFly;
public:
Animal(Fly &f);
void setFly(Fly &f);
Fly const &getFly();
};
Then you need to include headers into cpp. Example:
#include "Animal.h"
class Dog : public Animal <=== Compiler needs definition of Animal here
{
public:
Dog(Fly f);
};
Note the difference between following definitions:
Fly Animal::getFly()
{
return myFly;
}
Returns a copy of object stored in myFly.
Fly const &Animal::getFly()
{
return myFly;
}
Returns a constant reference to an object myFly
Also, perhaps, you do not need Fly, CanFly, CantFly classes at all. Classes Bird, Dog already "know" if they can or cannot fly. Sure, you are doing an exercise but still Fly, CanFly, etc seem to be redundant and artificial here.
In order to use a class, its definition is required. A statement like
class Fly;
is not a definition, but merely a declaration. A class that has been declared cannot be used, but you can define pointers and references to such a class.
So, to get your code working, you should split the code into header files (.hpp) containing the class definitions and source files (.cpp) containing the (non-inline) definitions of any class members declared in the headers.
Moreover, you seem to want to use polymorphism, but forgot to declare the member bool Fly::fly() to be virtual. I think what you want is
// file Fly.hpp
struct Fly
{
virtual bool fly() const = 0;
};
struct CanFly : Fly
{
bool fly()
{ return true; }
};
struct CantFly : Fly
{
bool fly()
{ return false; }
};
and then
// file Animal.hpp
struct Fly; // forward declaration
struct Animal
{
const Fly*const myFly; // use pointer to forwardly declared class
// const data member is public (serves as getter)
bool fly() const;
protected:
Animal(Fly const&f);
// no setter: an Animal cannot change its flying behaviour
};
and
// file Animal.cpp
#include "Fly.hpp"
#include "Animal.hpp"
Animal::Animal(Fly const&f)
: myFly(&f) {}
bool Animal::fly() const
{ return myFly->fly(); } // polymorphic call
However, I don't like this pattern. The problem is that in order to define a Bird or a Dog as derived from Animal, you need to provide a reference to an actual CanFly and CantFly, respectively, to the constructor of their base Animal. Moreover, there is nothing that qualifies an Animal other than whether it can fly or not, so why have this class Animal (in addition to Fly)?
change your fly.cpp to fly.h, in Animal.cpp you should #include<fly.h> Or just define your myFly as a pointer Fly* myFly.

Polymorphic Member Variable

I got an elegant answer yesterday for my question regarding polymorphic object members.
But now I am facing the problem that the variable isn't really behaving the way I expected it to. The following code is being used:
#include <iostream>
#include <math.h>
using std::cin;
using std::cout;
using std::endl;
class Com
{
public:
virtual void setReady()
{
cout << "Com" << endl;
}
};
class DerivedCom : public Com
{
public:
void setReady()
{
cout << "DCom" << endl;
}
void somethingElse()
{
cout << "else" << endl;
}
};
class BaseClass
{
public:
Com* com;
public:
BaseClass(Com* c = new Com) : com(c)
{
}
virtual void setReady()
{
com->setReady();
}
};
class DerivedClass : public BaseClass
{
// the call to somethingElse() won't compile if I leave out this declaration
protected:
DerivedCom* com;
public:
DerivedClass() : BaseClass(new DerivedCom)
{
}
void setReady()
{
// This line causes a segfault if I put in the declaration earlier
this->com->setReady();
// This line won't compile if I leave out the declaration earlier
this->com->somethingElse();
}
};
int main()
{
DerivedClass* inst = new DerivedClass();
inst->setReady();
return 0;
}
The problem is, that DerivedClass::com is in fact of type DerivedCom but I can't access any DerivedCom-specific methods as the compiler won't find them. If I put in an extra re-declaration DerivedCom* com, the compiler will find the methods but I get segmentation faults.
Remove that extra declaration.
If you are sure that a Com* is a DerivedCom* then you can static_cast it.
static_cast<DerivedCom*>(this->com)->somethingElse();
This will likely crash it you're wrong however. So if you are not sure then you can dynamic_cast it
DerivedCom* dcom = dynamic_cast<DerivedCom*>(this->com);
if (dcom)
dcom->somethingElse();
dynamic_cast will return NULL if the object isn't of the type you asked for.
The reason for the segmentation faults is that you arent declaring the variable again with a different type, you are actually defining a new pointer in the derived class, one that is never initialized. Thus this->com->... will access the derived class com and crash since it is an uninitialized pointer.
What you are trying to do though, is to change the type of the member pointer. You could do that by making the type of the member pointer as a template variable, as follows
template <class ComType>
class BaseClassTemplate
{
ComType* com;
...;
};
typedef BaseClassTemplate<Com> BaseClass;
class DerivedClass : public BaseClassTemplate<DerivedCom>
{
...;
};
However this makes the base class a template, so to get it as you want it, you need to make an instantiation of BaseClass<Com> to get your version of base class. You can either make it a derived class or just a typedef as i have shown.