I have encountered a problem with creating new class objects.
The abstract class is called SimpleList, currently doesn't do anything on its own.
template<class T>
class SimpleList {
public:
string ListName;
SimpleList(){
};
string getName(){
return ListName;
};
};
template<class T>
class Queue : public SimpleList<T> {
public:
string ListName;
Queue(string& name){
ListName = name;
}
string getName(){
return ListName;
}
};
And here is where I am attempting to assign 'pQLi' to a new Queue, where Queue is a derived class.
SimpleList<int> *pQLi;
if (indicator == 'i' ){
pQLi = new Queue<int>(name1);
}
But whatever I do to print out the name of pQLi (or access any data from it, but in the simplest case ) outside of the Queue, only ' ' is coming out. For example, if I do this
cout <<(*pQLi).getName() <<"\n";
Instead of printing out the ListName, a blank character comes out
its as simple as it is. Make your base class getName() virtual as follows. Since you are care of the content of pointer, you need a late binding of the object.
template<class T>
class SimpleList
{
public:
string ListName;
SimpleList() = default;
virtual string getName(){
return ListName;
};
};
However, I do not understand, why you need a template class for this. You have not used the type(T) anywhere.
And try to use initializer_list whenever possible and smart pointers are good to use in following cases. I have made a small correction as follows. Hope this has answered your question.
#include <iostream>
template<class T>
class SimpleList
{
private:
std::string ListName;
public:
SimpleList() = default;
virtual ~SimpleList(){}
virtual const std::string& getName()const
{ return ListName; };
};
template<class T>
class Queue : public SimpleList<T>
{
private:
std::string ListName;
public:
Queue(const std::string& name)
:ListName(name) {}
const std::string& getName()const
{ return ListName; }
};
int main()
{
SimpleList<int> *pQLi;
char indicator = 'i';
std::string name1 = "nothing";
if (indicator == 'i' ){
pQLi = new Queue<int>(name1);}
std::cout <<(*pQLi).getName() <<"\n";
delete pQLi;
pQLi = nullptr;
return 0;
}
Related
So i have this part of code
class Robot
{
public: string Name;
public: explicit Robot(const string& Name) { this->Name = Name; }
public: Robot() { Name = "Robotic"; }
public: virtual ~Robot() = default;
public: virtual vector<string> GetCapabilities() = 0;
public: friend ostream& operator << (ostream&, const Robot&);
};
class TalkingRobot : virtual public Robot
{
public: explicit TalkingRobot(const string& Name) { this->Name = Name; }
public: virtual ~TalkingRobot() = default;
public: vector<string> GetCapabilities() { return { "Talking" }; }
};
class WalkingRobot : virtual public Robot
{
public: explicit WalkingRobot(const string& Name) { this->Name = Name; }
public: virtual ~WalkingRobot() = default;
public: vector<string> GetCapabilities() { return { "Walking" }; }
};
class VaxBot : public TalkingRobot, public WalkingRobot
{
public: explicit VaxBot(const string& Name):TalkingRobot(Name), WalkingRobot(Name) { this->Name = Name; }
public: virtual ~VaxBot() = default;
public: vector<string> GetCapabilities() { return { "Talking","Walking" }; }
};
They have a virtual function GetCapabilites().
Is there a way to rewrite GetCapabilites() in my VaxBot class to return all the inherited classes return values so that i dont have to explicitly write them like i did in here?
There isn't a simple one-line way in standard C++ to implement this sort of thing. For example, there is no way for a derived class to iterate over all its base classes, and call some member function in every base to collect the results, without explicitly naming all the bases/members separately.
It is possible to call the inherited functions, and collect their results into a single vector. For example;
std::vector<std::string> VaxBot::GetCapabilities()
{
std::vector<std::string> values(TalkingRobot::GetCapabilities());
std::vector<std::string> more_values(WalkingRobot::GetCapabilities());
values.insert(values.end(), more_values.begin(), more_values.end());
return values;
}
The above can be extended if you have more than two such bases. That means explicitly replicating code but, as I said in my opening paragraph, there is no way to implement this sort of machinery implicitly.
There are other problems with your code, but you haven't asked about those, so I won't address them. And, for readability, don't use the text public: on every line. Posting code that is unnecessarily unreadable is an effective way to reduce your chances of getting useful help, since it sets other people's teeth on edge.
class Robot
{
public: string Name;
public: vector<string> Capabilities;
public: explicit Robot(const string& Name) { this->Name = Name; }
public: Robot() { Name = "Robotic"; }
public: virtual ~Robot() = default;
public: vector<string> GetCapabilities() { return this->Capabilities; }
public: friend ostream& operator << (ostream&, const Robot&);
};
class TalkingRobot : virtual public Robot
{
public: explicit TalkingRobot(const string& Name) {
this->Name = Name;
this->Capabilities.push_back("Talking");
}
public: virtual ~TalkingRobot() = default;
};
class WalkingRobot : virtual public Robot
{
public: explicit WalkingRobot(const string& Name) {
this->Name = Name;
this->Capabilities.push_back("Walking");
}
public: virtual ~WalkingRobot() = default;
};
class VaxBot : public TalkingRobot, public WalkingRobot
{
public: explicit VaxBot(const string& Name):TalkingRobot(Name), WalkingRobot(Name) { this->Name = Name; }
public: virtual ~VaxBot() = default;
};
You could utilize multiple inheritance constructors to store Capabilities.
Basically I have to store different movies in a heterogenous collection dynamically, I already have the different movie types (documentary and family) and the class which "masks" the difference (movie) so it can be stored in one place (record).
I'm having trouble with my addMovie(Movie *mov) function. I don't know how to start.
My Record class:
class Record {
String name;
size_t siz;
Movie* movies;
Record(const Record&);
Record& operator=(const Record&);
public:
Record(String n): name(n), siz(0) {movies = new Movie[siz+1];}
void addMovie (Movie *mov);
void removeMovie (Movie *mov);
void listMovies();
void searchMovie (const char* title);
void emptyRecord();
void writeFile();
void readFile();
virtual ~Record() {emptyRecord();}
};
Movie class:
class Movie {
protected:
String name;
String release;
String genre;
public:
Movie(){}
Movie(String n, String r, String g): name(n), release(r), genre(g) {}
virtual void write() {}
virtual ~Movie() {}
};
Documentary class: (the family class is similar, it stores an int age_restriction and the write function writes that)
class Documentary: public Movie {
String description;
public:
Documentary(String n, String r, String d = "Add description up to 50 characters!"): Movie(n,r,"Documentary"), description(d) {}
String getDescription () const {return description;}
void setDescription (String newdescr);
void write();
virtual ~Documentary(){}
};
(PS: if you have any good sources for dynamic heterogenous stores I'm all ears)
Not so clear requirements, but for storing heterogeneous data in one single container, I would advise std::tuple (https://en.cppreference.com/w/cpp/utility/tuple). Let me know if it's what you were looking for ;)
EDIT: a possible solution without STL.
#include <iostream>
using namespace std;
class Base {
};
class A : public Base {
};
class B : public Base {
};
int main(){
const size_t arraySize = 10;
Base* array[arraySize];
//allocate
array[0] = new A();
array[1] = new B();
// ...some more stuff here
//dispose
for (Base* ptr : array) {
if (ptr != nullptr) {
delete ptr;
ptr = nullptr;
}
}
}
Say I have this class called Dog. Every dog has a different name but the same barking voice (which is loaded from a resource file).
class Dog {
public:
Dog(const string &name) : _name(name) {
_barkingVoice.load();
}
~Dog() {
_barkingVoice.free();
}
string getName() const { return _name; }
void bark() { _barkingVoice.play(); }
private:
string _name;
VoiceResource _barkingVoice;
};
I want to call _barkingVoice.load() only if the instance of Dog is the first one, and _barkingVoice.free() only if there are no more instances of Dog.
The obvious solution is to set _barkingVoice as static and keep a reference counter of Dog as a data member.
My question is if there's an easier way to do this. Maybe an std implementation or something like that.
Make a reusable class to encapsulate the reference counting:
template<class ResourceType, class OwnerType>
class RefCounted {
public:
RefCounted() { if (++_refCount == 1) _resource.load(); }
virtual ~RefCounted() { if (--_refCount == 0) _resource.free(); }
ResourceType& operator*() { return _resource; }
ResourceType* operator->() { return &_resource; }
private:
static unsigned _refCount;
static ResourceType _resource;
};
template<class T, class U> unsigned RefCounted<T, U>::_refCount = 0;
template<class T, class U> T RefCounted<T, U>::_resource;
class Dog {
public:
Dog(const string &name) : _name(name) { }
string getName() const { return _name; }
void bark() { _barkingVoice->play(); }
private:
string _name;
RefCounted<VoiceResource, Dog> _barkingVoice;
};
Every template instantiation will have their own _refCount and _resource.
The second template parameter is to handle cases where you instantiate RefCounted with the same ResourceType but want to have separate reference counting for those instantiations. E.g. if you add a Cat class and want it to have its own Refcounted<VoiceResource>:
class Cat {
// ...
private:
RefCounted<VoiceResource, Cat> _meowingVoice;
};
First, why VoiceResource is not static? If it's shared between all instances of Dog, it should be. Else, you will need to load or copy the resuorce at every constructor call.
Have a static variable static int instanceCount;, that is set to 0. In every casual, copy and move (C++11) constructor increment it, in destructor decrement it. That will give you opportunity to do what you wanted.
That will basicly work like shared_ptr<T> does, the might be a way to use it here instead of writing your own code, I just can't figure that out.
class Dog {
public:
Dog(const string &name) : _name(name) {
loadResource();
}
Dog(const Dog& b) : name(b.name) {
loadResource();
}
// only C++11:
Dog(Dog&& b) : name(std::move(b.name)) {
loadResource();
}
~Dog() {
freeResource();
_barkingVoice.free();
}
string getName() const { return _name; }
void bark() { _barkingVoice.play(); }
private:
string _name;
static VoiceResource _barkingVoice;
static int instanceCount;
static void loadResource() {
if (instanceCount == 0) {
_barkingVoice.load();
}
++instanceCount;
}
static void freeResource() {
--instanceCount;
if (instanceCount == 0) {
_barkingVoice.free();
}
}
};
int Dog::instanceCount = 0;
Make _barkingVoice a std::shared_ptr<VoiceResource>.
A shared_ptr does exactly what you need: uses references counting to track the deletion of the last object, when it will deallocate the resource.
I have one problem on conversion of one class to base.
This is the code :
#define Derive_NTag_CRTP(Type) class Type: public NTagBase<Type>
template<typename Derived>
class NTagBase{
public:
NTagBase(var name) { this->_name = name; }
NTagBase(const NTagBase & ntag) { this->_name = ntag._name; }
NTagBase* append(NTagBase<Derived> *item) { _children.push_back(item); return this; }
private:
var _name;
vector<NTagBase *> _children;
};
Derive_NTag_CRTP(NTag){
public:
NTag(var name) : NTagBase(name) { }
NTag(const NTagBase & ntag) : NTagBase(ntag) { }
};
Derive_NTag_CRTP(NTagInput){
public:
NTagInput(var type) : NTagBase("input") { _type = type; }
NTagInput(const NTagBase & ntag) : NTagBase(ntag) { }
private:
var _type;
};
int main(int argc, char **argv, char **envv)
{
NTag div("div");
NTagInput button("button");
div.append(new NTag("span"));
div.append(&button);// Error 1 error C2664: 'NTagBase<Derived>::append': can not convert parameter 1 from 'NTagInput *' to 'NTagBase<Derived> *'
}
How can I fix that without do one explicit cast?
PS: I need to have one vector of pointers of base class and append into that all kind of classes inherited.
div is NTag, i.e. NTagBase<NTag>. button is NTagInput, i.e. NTagBase<NTagInput>, while div's append() expects a NTagBase<NTag> which is unrelated. You should change append to something like
template <typename D>
NTagBase* append(NTagBase<D> item) { ... }
However, you still cannot store items of different types in a single vector. Better make a non-template e.g. Base of NTagBase and let your vector contain pointers (or std::unique_ptr) to Base.
div.append (...) clearly need to be overloaded because after inherited from the base, it wouldn't understand the second signature ie div.append(&button); or you can create a wrapper class that pack every object type to it own define and provide a mechanism for reversing back to the original type.
Alternatively , just overload any necessary function .
class NTagInput;
class AppendInputRegister;
template<typename Derived>
class NTagBase{
public:
NTagBase(string name) { this->_name = name; }
NTagBase(const NTagBase & ntag) { this->_name = ntag._name; }
NTagBase* append(NTagBase<Derived> *item) {
_children.push_back((NTagBase *)item);
return this;
}
private:
string _name;
vector<NTagBase *> _children;
};
class NTag: public NTagBase<NTag>{
public:
NTag(string name) : NTagBase(name) { }
NTag(const NTagBase & ntag) : NTagBase(ntag) { }
NTagBase* append(NTagBase<NTagInput> *item) {
append((NTagBase<NTag> *)item);
}
NTagBase* append(NTagBase<NTag> *item) {
NTagBase::append((NTagBase<NTag> *)item);
}
};
class NTagInput: public NTagBase<NTagInput>{
public:
NTagInput(string type) : NTagBase("input") { _type = type; }
NTagInput(const NTagBase & ntag) : NTagBase(ntag) { }
private:
string _type;
};
I Have two classes:
First:
class Thing {
public:
int code;
string name;
string description;
int location;
bool canCarry;
Thing(int _code, string _name, string _desc, int _loc, bool _canCarry) {
code = _code;
name = _name;
description = _desc;
location = _loc;
canCarry = _canCarry;
}
};
Second:
class Door: public Thing {
private:
bool open;
public:
int targetLocation;
Door(int _code, string _name, string _desc, int _loc, int _targetLoc) :
Thing(_code, _name, _desc, _loc, false) {
open = false;
targetLocation = _targetLoc;
}
void Use() {
open = true;
}
void Close() {
open = false;
}
bool isOpen() {
return open;
}
};
Forget private/public atributes...
I need to store some objects of base class and some objects of derived class,
something like this:
vector < Thing*> allThings;
things.push_back(new Thing(THING1, "THING1", "some thing", LOC1, true));
things.push_back(new Door(DOOR1, "DOOR1", "some door", LOC1, LOC2));
But in this case, functions Use(), Open(), and isOpen() will not be reachable because of slicing..
Do you have some suggestions, how to store these objects together without creating new structure of vector<Thing*> and vector<Door*>??
Thanks
A good solution to a problem when you need a container of objects with polymorphic behavior is a vector of unique pointers:
std::vector<std::unique_ptr<Thing>>
There would be no slicing in this situation, but you would have to figure out when it's OK to call Use(), Open(), and isOpen().
If you can move the methods from the derived class into the base, go for it; if you cannot do that because it makes no sense for a Thing to have isOpen(), consider using a more advanced solution, such as the Visitor Pattern:
class Thing;
class Door;
struct Visitor {
virtual void visitThing(Thing &t) = 0;
virtual void visitDoor(Door &d) = 0;
};
class Thing {
...
virtual void accept(Visitor &v) {
v.visitThing(*this);
}
};
class Door : public Thing {
...
virtual void accept(Visitor &v) {
v.visitDoor(*this);
}
}
Store pointers instead of instances, and declare public and protected methods as virtual in the base class(es).