Derived class initialization with parameter of another derived class - c++11

I am new in Abstract classes so please excuse any ignorant mistakes
The exercise is given from my school, so the main.cpp file is to be used, almost as it is
I am trying to create a simple calculator in Eclipse using C++11
There exists a simple Abstract class with two virtual methods.
The two derived classes are simply the "Result" and the "Const" classes.
This is the header file of the Abstract class called
Expression.h
class Expression
{
public:
Expression();
virtual ~Expression();
//methods
};
Following is the source file of Expression
Expression.cpp
#include "expression.h"
#include <iostream>
Expression::Expression(){}
Expression::~Expression(){}
Then I have created two classes called Const and Result
Const.h
#include <iostream>
#include "expression.h"
class Const : public Expression
{
public:
Const(int value);
//inherited methods
private:
int value;
};
and the source file
Const.cpp
#include "expression.h"
#include "Const.h"
Const::Const(int x)
{
value=x;
};
//inherited methods
Result.h
#include <iostream>
#include "expression.h"
#include "Const.h"
class Result : public Expression
{
public:
Result(Const& c);
//inherited methods
private:
double value;
};
Result.cpp
#include "expression.h"
#include "Result.h"
Result::Result(Const& c)
{
value=c.point;
};
//inherited methods
So what i need is to understand
main.cpp
#include <iostream>
#include "expression.h"
#include "const.h"
#include "result.h"
void testResult()
{
Result res (new Const(4));
//Here an inherited method will be used to print the contents of object res
}
int main()
{
testResult();
return 0;
}
The problem i can't solve is the line
Result res (new Const(4));
The error i get is
Conversion from 'Const* to non-scalar type 'Result' requested
The thing is that what is described in this line should be used as it is, and i can't seem to find exactly what it is.
EDIT
The question as asked firstly was apparently misleading due to my fault, tried to fix the question so as to describe exactly my problem

You started correctly, by creating a common base class for both Const and Result, but then completely ignored it.
All your problems are indeed in this line:
Result res = (new Const(4));
First of all, operator new in C++ returns a pointer, not a reference. Also, this would be a good place to make use of your base class:
Expression* res = new Const(4);
Since you declared methods evaluate() and print() as virtual, the object res is pointing to will be correctly resolved as an instance of Const when you call res->print() or res->evaluate().
This will use Const version of print(). If you want to use the Result version - abstract classes won't help you here, you need to use casting. Create your own operator=(Const &) in Result or operator Result() in Const.

If you had two derived classes DerivedClass1 and DerivedClass2 both derived from some BaseClass then to instantiate a pointer to a DerivedClass1 and use it in polymorphic way use:
BaseClass* p = new DerivedClass1;
To create a base class pointer to a DerivedClass2 use:
BaseClass* p = new DerivedClass2;
And not the:
DerivedClass1* p = new DerivedClass2;
In your example both Result and Const classes are derived from Expression class hence the confusion. To pass in an argument of SomeClass& type, create a temporary object of SomeClass and pass it in:
SomeClass o;
someFunction(o);

One issue is that
double point= value;
doesn't initialize your member, but a new unused local variable.
just do
point = value;

Class Result and Const are two different classes. This means the type conversion
Result *res = (new Const(4));
is not possible. To do what you want, since both classes inherit from Expression, do:
Expression * res = new Result( objConst);
Where objConst is a Const object.

Related

C++: convert not from obj1 to obj2, but from obj1* to obj2?

A constructor for MyClass takes a pointer to another such object.
The C++ MyClass is functionally the same as a C "class" based on a typedef'd struct called MyType_T. (The C++ class is basically a wrapper to the old C code.) I'd like to be able to pass in a MyClass* anywhere I could pass in a MyType_T* before.
I'd like to write an automatic conversion of any MyClass* to MyType_T*, but I guess what's throwing me is that my type converter is written to take a MyClass not a MyClass*. Even though I'm sure that's the problem, I can't think of what syntax would solve it. I've thought about making a friend implementation of the cast, but I can't put it before the definition of class MyClass because it won't know the offset of thing. And I can't put after the definition of class MyClass because the MyClass constructor wants to use that conversion.
typedef struct MyStruct {
int iFoo;
struct MyType* ptypeParent;
} MyType_T;
void MyTypeCreator( MyType_T* ptypeSelf, int iFoo_in, MyType_T* ptypeParent );
class MyClass {
public:
MyClass( int iFoo, MyClass* pclassParent ) {
MyTypeCreator( &thing, iFoo, pclassParent ); <--------------- PROBLEM
MyTypeCreator( &thing, iFoo, &pclassParent->thing ); <------- WORKS
};
operator MyType_T*() { return &thing; } <---------------- INCORRECT: attempts to convert MyClass, not MyClass*, to MyType_T*.
MyType_T thing;
};
QUESTION 1: how to write a convertor from MyClass* instead of MyClass?
QUESTION 2: how can such a convertor check for NULL input? (If thing isn't offset of 0, but say 8, then converting from a NULL pclass without a check would give a value of 0x00000008, not NULL...)

no viable conversion from 'shared_ptr<src::IdInterface>' to 'shared_ptr<IdInterface>'

I am trying to understand an error I see when attempting to implement the Visitor pattern for validation purpose. When i execute cmake ../ from the build directory i am getting the following error:
validator/src/Id.cpp:30:38: error: no viable conversion from 'shared_ptr<src::IdInterface>' to 'shared_ptr<IdInterface>'
bool isValid = validator->isValid( castedObj );
/home/tito/Projects/validator/src/IdValidatorInterface.h:24:50: note: passing argument to parameter 'entity' here
virtual bool isValid( shared_ptr<IdInterface> entity ) = 0;
I have been able to replicate the error with simple 3 classes For the sake of the example i have put them in the same namespace.
Those classes are "Id" class this is the element i would like to validate. The Id inherits from BasePrimitive. The sole purpose of BasePrimitive class is to be able to get a share pointer validating entity since the BasePrimitive class inherits from
"enable_shared_from_this". i.e. the code below
#include "Id.h"
#include "IdInterface.h"
#include "IdValidatorInterface.h"
#include <iostream>
using namespace std;
namespace src
{
const string Id::name = "ID";
Id::Id()
{
}
Id::~Id()
{
}
bool Id::validate(shared_ptr<IdValidatorInterface> validator)
{
shared_ptr<Id> thisObj = shared_from_this();
shared_ptr<IdInterface> castedObj = static_pointer_cast<IdInterface>(thisObj);
bool isValid = validator->isValid( castedObj );
if (!isValid)
{
vector<string> vectorOfErrors = validator->validate(castedObj );
std::cout << " the Id has NOT been validated" << std::endl;
} else
{
std::cout << " the Id has been validated" << std::endl;
}
return isValid;
}
string Id::getName() const {
return Id::name;
}
}
the part where the code is broken is this one: Here i get a share_ptr from this class and then do a static pointer case. This works well but when i try to pass it to the isValid method then it breaks.
shared_ptr<Id> thisObj = shared_from_this();
shared_ptr<IdInterface> castedObj = static_pointer_cast<IdInterface>(thisObj);
bool isValid = validator->isValid( castedObj );
and the BasePrimitive class
namespace src {
class BasePrimitive: public enable_shared_from_this<BasePrimitive> {
public:
~BasePrimitive();
BasePrimitive();
};
}
Then i have my validator class i.e. IdValidator
#include "IdValidator.h"
#include "Id.h"
#include "IdInterface.h"
using namespace std;
namespace src
{
using Id = src::Id;
IdValidator::IdValidator()
{
}
bool IdValidator::isValid(shared_ptr<IdInterface> entity)
{
vector<string> listOfErros = validate(entity);
if(listOfErros.empty() ){
return false;
}else{
return true;
}
}
vector<string> IdValidator::validate(shared_ptr<IdInterface> entity)
{
vector<string> stringList = vector<string>();
// do some validation of the name
string name = entity->getName()
if (name == "BadName")
{
string error = "Error. id name is bad";
stringList.push_back(error);
return stringList;
}
return stringList;
}
}
And i do have 3 other interfaces i.e. BaseElementValidatorInterface, IdValidatableInterface, IdValidatorInterface which are there simply for explicit in order to state that those a pure virtual functions.
in the last interface i.e. IdValidatorInterface i am using a forward declare to the IdInterface in order to avoid cyclic includes.
i.e.
class IdInterface;
The first probelm:
"no viable conversion from 'shared_ptr' to 'shared_ptr'"
the only difference here i see is the full qualified namespace. I would like to understand the nature i.e. the origin of this error. Is this something related to the compiled definitions I pass to clang i.e.
add_definitions(" -pedantic -pedantic-errors -W ")
add_definitions(" -Wall -Wextra -Werror -Wshadow -Wnon-virtual-dtor ")
add_definitions(" -v ")
or something else.
I have found multiple articles in stackoverflow about this but all of those were mainly about different types i.e. somethig like bools and string.
like this one
no viable conversion from 'int' to 'Time'
No viable conversion from 'bool' to 'std::string'
I do understand the articles mentioned above, but in my case the compiler is seeing the same type except the namespace is different i.e.'shared_ptr' to 'shared_ptr' how to i tell the compiler that those are the same objects? Why is the compiler seeing different namespaces when this is the same class i.e. "IdInterface". In some of the articles above it has been mentioned that this error can be seen if the class in not defined , but for this reason i use explicetelly the fotrward declaration.
I have put those whole 3 classes and the 3 interfaces on github to show the complete picture. https://github.com/courteous/visitor/tree/master/src
Any help is highly appreciated

C++: template class inheritance with variable-type parameters using parameter packs

(I had no idea how to name this question and I couldn't find anything similar. Sorry if this is duplicate)
If I want to inherit from some base template class, I can do this that way:
template<typename A=int, typename B=char> class C {};
template<typename... Args> class D : public C<Args...> {}; //it works!
This way I can change in project passed parameters to template class C and I don't have to change every usage of class D. Great. But what if I have template class using not only types as parameters but also values? For example:
template<int dim=3, typename float_t=double> class GeometricObject{};
template<typename... Args> class Point : public GeometricObject<Args...>{}; //it doesnt work
Of course I could define last template with integer type on the beginning. But this is not a way, if I would have 100 different classes all inheriting from GeometricObject and then I would change default dim value to 2, I would have to change every single class definition.
I also hope that there is the way without using any #define, #else and similar preprocessor commands. I know that templates are in fact also preprocessor commands, but... well, let's be modern here ;)
You can not mix type and non-type parameters in a template parameter pack. But it seems that your Point and other derived classes don't need to access the parameter pack arguments separately. In such cases it's easier, as well as more semantically correct, to pass the base class:
template<int dim=3, typename float_t=double> class GeometricObject{};
template<class GeometricObject=GeometricObject<>> class Point : public GeometricObject{};
Instantiating a Point could then look like:
Point<> a{}; // the same as Point<GeometricObject<>> a{};
Point<GeometricObject<4>> b{};
Point<GeometricObject<2, float>> c{};
Of course the GeometricObject<...> could be typedef'd to something shorter. Also, it can be made to look like a namespace instead of providing parameters to each geometric object separately:
template<int dim = 3, typename float_t = double>
struct GeometricObjects {
using Base = GeometricObject<dim, float_t>;
using Point = ::Point<Base>;
// ...
};
using TwoDim = GeometricObjects<2>;
TwoDim::Point a{};
I suppose you have multiple template classes and you want your Point object to be able to inherit from them all.
Instead of doing:
template <typename ... Args>
class Point : public GeometricObject<Args...>{};
I would instead do:
template <typename T>
class Point : public T {};
Now we just have to define proper traits to access the types template parameters in case they are needed. These types should be factored into a std::tuple (for instance).
The burden to fill this trait is on the GeometricObject class. For example, with your definition we would have:
template <typename T>
struct type_parameters;
template <int N, typename Float>
struct type_parameters<GeometricObject<N, Float> {
typedef std::tuple<Float> types;
};
The main scenario: a method of Point needs the type template parameters of GeometricObject (to forward them to a method of GeometricObject). To achieve this, you will have to pass in a tuple that will be unfold to call the inner method. To do so I make use of features added in the STL for C++14. You could still rewrite them yourself but I spared me the hassle for this question...
template <typename T>
class Point : public T {
template <typename Method, typename ... Args, std::size_t ... Is>
auto call_unfold(Method method, std::tuple<Args...> const& tuple, std::integer_sequence<std::size_t, Is...>) {
return (this->*method)(std::get<Is>(tuple)...);
}
template <typename Method, typename Tuple>
auto call_unfold(Method method, Tuple const& tuple) {
return call_unfold(method, tuple, std::make_index_sequence<std::tuple_size<Tuple>::value>());
}
public:
typedef typename type_parameters<T>::types types;
void some_method(types const& args) {
return call_unfold(&T::some_method, args);
}
};
This example is quite meaningless but the same technique could be useful with constructors of Point that need to call a base class constructor.
A live demo showing how it works is available on Coliru
Ok, so I figured it out how I should include variable-type template parameters into tuples. Basically I need to 'encapsulate' them into new parameter. This example works perfectly well AND solves my problem:
#include <type_traits>
template<int n = 2> struct Dim {
const int dim = n;
};
template<typename T> class SillyBaseClass {
public:
typedef typename T dim;
};
template<typename... Args> class SillyDerivedClass : public SillyBaseClass<Args...>{
public:
typedef typename SillyBaseClass::dim dim;
SillyDerivedClass() {
static_assert(std::is_same<dim,Dim<2>>::value,
"Number of dimensions must be equal to 2");
}
};
int main() {
SillyDerivedClass<Dim<2>> Class2d; //this works
SillyDerivedClass<Dim<3>> Class3d; //this returns expected error
}

Should this simple structure have an implicit move constructor?

In this test:
#include <string>
struct thing {
std::string name_;
};
class test {
thing id_;
public:
test(thing id) : id_{std::move(id)} {}
};
I would expect struct thing to have an implicit move constructor, so that class test can use std::move() to initialise its data member.
Clang version 3.4.1 gives this error:
error: no viable conversion from 'typename remove_reference<thing&>::type' (aka 'thing') to 'std::string' (aka 'basic_string<char, char_traits<char>, allocator<char> >')
The problem can be solved by adding a move constructor to struct thing, which of course means that a converting constructor and an explicitly defaulted copy constructor also needs to be added.
I do not understand why I cannot move struct thing around implicitly.
You are using a brace initialization - id_{std::move(id)}. In your case, as though struct thing is a POD (plain old data) it means, that C++ compiler tries to initialize the first member - std::string name_ instead of using a default constructor of struct thing object. Read more about aggregates and PODs.
In this case, because of the braces, class test's constructor is equivalent to something like this:
class test {
thing id_;
public:
test(thing id) {
id_.name_ = std::move(id); // Notice that this causes
// the "no viable conversion" error
}
};
Solution 1: You need to declare explicitly that you want to use a default struct thing's constructor by using parenthesis instead of braces:
#include <string>
struct thing {
std::string name_;
};
class test {
thing id_;
public:
test(thing id) : id_(std::move(id)) {} // Default c-tor will be used
};
Solution 2: You could also declare a user-defined constructor of struct thing to make it non-POD:
#include <string>
struct thing {
std::string name_;
thing(thing&&) {} // Used-defined move constructor
};
class test {
thing id_;
public:
test(thing id) : id_{std::move(id)} {} // You can use braces again
};

Single instance of an object

I'm trying to implement a singleton-like object with C++11. I got this example from another user.
It creates an object with the constructor and the copy constructor private and default, as well as an instance() function to return static object.
As I understand this should prevent the creation of two instances of this object. But as you can see in my main.cpp, I create two instances and it compiles and runs.
Is my object creation wrong or what? I don't get it.
object.hpp:
#ifndef OBJECT_H
#define OBJECT_H
#include <iostream>
using namespace std;
class Object
{
private:
Object() = default;
Object(const Object&) = delete;
public:
// Singleton in C++11
static Object& instance() { static Object z; return z; }
};
#endif // OBJECT_H
main.cpp:
#include "object.hpp"
int main()
{
Object* object = new Object();
object->instance();
Object* object2 = new Object();
object->instance();
return 0;
}
When I try to compile your code, I get a proper error from the compiler:
main.cpp: error: calling a private constructor of class 'Object'
Object* ob1= new Object() ;
So I would not be able to create two objects using new.
First your code in main won't compile. Object default constructor is private, so you won't be able to do :
Object* object = new Object();
Second, as instance() is static (means not related to any instance) there is no need to call it from an object, the class name suffices :
Object& theInstance = Object::instance();
Finally, the code of instance is :
static Object& instance()
{
static Object z;
return z;
}
It's OK. A static variable in a C++ function means that the object is instanciated once : when the function is ran for the first time. Then z won't be destroyed at the end of the function (contrary to other so-called local variables) and will be re-used for next calls of instance.
So at first call of instance :
z is created
z z is returned
At next calls :
z is returned
A singleton is a class which implies only one instance will be created. You can verify the objects are the same with :
Object& a = Object::instance();
Object& b = Object::instance();
std::cout << &a << std::endl;
std::cout << &b << std::endl;
a and b should have the same memory adress.
This is the expected behaviour of a singleton : if the object construction function (instance) is called several times, the same instance will be returned.
So as you said, instance actually prevents the creation of two Object. Maybe you expected you program to return some error on the second call of instance. If you wan't this behaviour, you'll have to make it yourself using expections or returning NULL. Yet, The code you wrote shows the classic way singletons are done in C++.

Resources