c++ autoconvert inherited class to base class - c++

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;
};

Related

What is the most intuitive layout for a class that manages pointers to different types?

I have a class that manages a map of strings and pointers as such:
class DebugTab
{
public:
void pushItem(std::string&& name, std::unique_ptr<DebugItem> item);
private:
std::map<std::string, std::unique_ptr<DebugItem>> items_;
};
The pointers should be able to point to different types so to achieve this I made this simple abstract class:
class DebugItem
{
public:
virtual std::string asString() = 0;
};
And then made a few derived classes for fundamental types:
class DebugInt : public DebugItem
{
public:
DebugInt(int& i) : i_(i) {}
std::string asString() override {return std::to_string(i_);}
private:
int& i_;
};
class DebugFloat : public DebugItem
{
public:
DebugFloat(float& f) : f_(f) {}
std::string asString() override {return std::to_string(f_);}
private:
float& f_;
};
class DebugString : public DebugItem
{
public:
DebugString(std::string& s) : s_(s) {}
std::string asString() override {return s_;}
private:
std::string& s_;
};
My idea was that the person using DebugTab would create the item with the correct class on the heap using 'new' and then pass the pointer to pushItem like this:
DebugTab tab;
int var1;
float var2;
std::string var3;
tab.pushItem("var1", std::move(std::make_unqiue<DebugInt>(var1)));
tab.pushItem("var2", std::move(std::make_unique<DebugFloat>(var2)));
tab.pushItem("var3", std::move(std::make_unique<DebugString>(var3)));
I'm not very satisfied with this solution. I feel that it just isn't very intuitive to pass a heap pointer to a class that tracks already created variables.
Is there a better, simpler way of doing all of this that comes to mind, or is the system I have now sufficient?
Well, technically you can skip allocating them at callsite...
template<class T>
struct DebugConcrete: DebugItem {
T &t;
std::string asSring() const override {
return std::to_string(t);
}
};
class DebugTab {
template<class T>
void pushItem(std::string name, T &item) {
items_.emplace(std::move(name),
std::make_unique<DebugConcrete<T>>(item));
}
};
#define pushItem(...) pushItem(#__VA_ARGS__, __VA_ARGS__)
int main() {
int i;
DebugTab tab;
tab.pushItem(i);
}

Cannot implement base class with virtual getters that are defined in child classes

I have a class that is called Object, this class's header is:
class DLL_SPEC Object {
public:
Object();
virtual ~Object();
virtual std::string getString() const;
virtual void setString(std::string value);
virtual int getInt() const;
virtual void setInt(int value);
virtual double getDouble() const;
virtual void setDouble(double value);
virtual bool isType(FieldType type) const;
};
And my child classes are as follows:
class DLL_SPEC IntObject : public Object {
public:
IntObject() : value(0) {}
IntObject(int v) : value(v) {}
void setInt(int value) override { this->value = value; };
int getInt() const override { return this->value; };
bool isType(FieldType type) const override;
private:
int value;
};
class DLL_SPEC DoubleObject : public Object {
public:
DoubleObject() : value(0.0) {}
DoubleObject(double v) : value(v) {}
void setDouble(double value) override { this->value = value; };
double getDouble() const override { return this->value; };
bool isType(FieldType type) const override;
private:
double value;
};
class DLL_SPEC StringObject : public Object {
public:
StringObject() : value("") {}
StringObject(std::string v) : value(v) {}
void setString(std::string value) override { this->value = value; };
std::string getString() const override { return value; };
bool isType(FieldType type) const override;
private:
std::string value;
};
Now, the problem is, I have an array of Objects and I want to get a string representation of a StringObject.
I call array[0].getString() and even though the object is of type StringObject, the method that gets called is the one is the base class, which I understand.
So, how would I go about implementing that whenever I call getString() on the base class it goes to the child one of the SAME object?
I've tried using this method:
std::string Object::getString() const
{
return dynamic_cast<StringObject*>(this).getString();
}
but then I get an error stating I cannot cast away const or any type qualifier, which is fixed by deleting const modifier (which I MUST leave there as it's according to the task), but then I get another one stating that no suitable constructor exists. So how would I go about implementing this and getting this base class to use the one of the child one?
EDIT: Added a small example that goes into the getString method of Object class and not the StringObject class.
int findPersonId(std::string whereName)
{
Db* db = Db::open("database");
Table* people = db->openTable("table");
auto iteratorTable = table->select();
while (iteratorTable->moveNext())
{
for (size_t i = 0; i < table->getFieldCount(); i++)
{
if (table->getFields()[i]->getName() == "id")
{ //this one beneath goes to the base class and not StringObject
std::string foundRow = iteratorPeople->getRow()[i]->getString();
if (foundRow == whereName)
{
return iteratorTable->getRowId();
}
}
}
}
return 0;
}
Note: The Table* is 2D array that consists of Object** (array that contains StringObject, IntObject, DoubleObject). The method .getRow() return the Object** array that consists of StringObject ...
The way I initiate the objects that go into the array is
Table* table= db->openOrCreateTable("table", 2, userFields); //this creates a 2d array
StringObject* name = new StringObject("Joseph");
IntObject* id = new IntObject(5);
Object** row = combineToRow(id, name);
table->insert(row); //insert an array into 2D array
The method combineToRow is just a simple convertor to Object**.
template<typename A, typename B>
Object** combineToRow(A a, B b) {
return new Object * [2]{ a, b };
}
You have not implemented a getString method for your IntObject, and since you didn't override it you are calling the base method. Once you implement it like this
class IntObject : public Object {
...
virtual std::string getString() const { return std::to_string(value); };
...
};
then you can call it.
int main(){
StringObject* name = new StringObject("Joseph");
IntObject* id = new IntObject(5);
Object** row = combineToRow(id, name);
std::cout << row[0]->getString() << " " << row[1]->getString();
}
5 Joseph
See working version here

New derived class from abstract classes

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;
}

Ideas on class Parameter structure given implementation

Question simplified: an expression is a parameter. It includes 2 objects of type parameter. But, is that parameter a string_class, ID_class, or Expression_class parameter? If I just say Parameter, it won't have these certain characteristics, will it? How do I have these objects, use logic, and then I can know if the private data members of Expression are string, id, or expression parameters? Sometimes I want that left parameter to be an expression, sometimes I want it to be a string, sometimes an ID.
class Parameter
{
public:
private:
};
class String_class : public Parameter
{
public:
String_class(string in_string)
private:
string my_string;
};
class ID_class : public Parameter
{
public:
insert_id(string in_ID);
private:
string my_ID;
};
class Expression_class : public Parameter
{
private:
Parameter left_parameter;
Parameter right_parameter;
string op;
public:
};
Lots of ways to do this...
enum ParameterType{
PT_INVALID_TYPE = -1,
PT_OPERATION_TYPE= 0,
PT_STRING_TYPE,
PT_ID_TYPE,
PT_INT_TYPE,
...
PT_MAX_TYPES
}
class Parameter {
public:
...
virtual ParameterType GetType() = 0;
virtual string ToString() = 0; // GetValue(), etc...
}
class String_class : public Parameter
{
public:
String_class(string in_string){}
virtual ParameterType GetType() override { return PT_STRING_TYPE; }
virtual string ToString() override {return my_string;};
private:
string my_string;
};
class ID_class : public Parameter
{
public:
insert_id(string in_ID);
virtual ParameterType GetType() override { return PT_ID_TYPE; }
virtual string ToString() override {return my_ID;};
private:
string my_ID;
};
enum OperationType {
OP_INVALID_OP = -1,
OP_CONCATENATE = 0,
OP_ADD,
OP_COMPARE_EQUAL,
OP_COMPARE_LESS_THAN,
OP_XOR,
... // whatever
OP_MAX,
}
class Expression_class : public Parameter
{
private:
Parameter* left_parameter;
Parameter* right_parameter;
string op;
public:
};
Some usage examples...
class Expression_class : public Parameter
{
private:
Parameter* left_parameter;
Parameter* right_parameter;
string op;
public:
Expression_class(string _op, Parameter* lhs, Parameter* rhs):
left_parameter(lhs), right_parameter(rhs), op(_op)
{
// alternatively
left_parameter = lhs;
right_parameter = rhs;
op = _op;
}
~Expression_class(){
left_parameter = nullptr;
right_parameter = nullptr;
}
virtual ParameterType GetType() { return PT_OPERATION_TYPE; };
virtual string ToString() { return eval(); }
protected:
string eval() {
if(left_parameter.GetType() != PT_ID_TYPE) return "Invalid left_parameter.";
if(right_parameter.GetType() != PT_STRING_TYPE) return "Invalid right_parameter";
switch(op){ // op is better as OperationType than string
case OP_CONCATENATE : return left_parameter.ToString() + " " + right_parameter.ToString();
// ...
}
if(CompareNoCase(op, "+") == 0)
return left_parameter.ToString() + " " + right_parameter.ToString();
return "Invalid Opertaion";
}
};
String_class employee_name("Rick");
String_Id employee_id("007");
Expression_class exp(OP_CONCATENATE, &employee_id, employee_name);
return exp.ToString();
Notes This is not the only way to do it, and as you use your class, you'll figure out short cuts to do less work.

C++ Inheritance, retrieving children's data members

I am trying to do this:
class Parameter
{
public:
Parameter(){};
~Parameter(){};
};
class Address : public Parameter
{
public:
Address(uint16_t val) : value(val){};
Address(const Address& b) : value(b.value){};
~Address(){};
private:
uint16_t value;
};
class Constant : public Parameter
{
public:
Constant(int val) : value(val){};
Constant(const Constant& b) : value(b.value){};
~Constant(){};
private:
int value;
};
How can I add set and get methods for the parent class Parameter so that when I create a Constant or Address object, I can use the parent methods to set and get the variable value?
Not sure what you meant, but here is a try:
template <typename T>
class Parameter
{
public:
const T& getValue() { return value; }
protected:
T value;
};
class Address : public Parameter<uint16_t>
{
public:
Address() { value = 2154; }
// ...
}
class Name : public Parameter<std::string>
{
public:
Name() { value = "John Doe"; }
// ...
}
Later you can do:
Address address;
Name name;
cout << name.getValue() << " lives at house no " << address.getValue();
// outputs "John Doe lives at house no 2154".
You could implement it as a pure virtual function and over ride it in the below classes?