Empty constructor and value passing problem - c++

When I create a class A object with a reference to class C, class B gives the error of:
Error C2512 'A': no appropriate default constructor available
Class A
class A
{
public:
C* cPointer;
A(C* arg)
{
cPointer = arg;
}
};
Class B
class B:
public A
{
public:
B()
{
}
};
If I add an empty constructor to class A it doesn't give errors but when I try to access cPointer it returns an empty address of 0000000000;
A()
{
}
How can I solve this problem?
Edit: example
int main()
{
C cObject;
A a(&cObject);
return 0;
}
Result: Severity Code Description Project File Line Suppression State
Error C2512 'A': no appropriate default constructor available
As I mentioned before if I put empty constructor to A it works but i cant use cPointer because it set to 0.
in class B:
cout << "Poniter: " << cPointer << endl;
result:
Pointer: 0000000000000000
Okay here is the actual code:
Skill.h (class C in example)
#pragma once
#include <iostream>
#include <vector>
#include "Unit.h"
using namespace std;
class Skill
{
public:
Unit* unitPtr;
Skill()
{
}
Skill(Unit* unit)
{
unitPtr = unit;
}
void SetUnit(Unit* unit)
{
unitPtr = unit;
}
vector <Skill *> attacks;
vector <Skill *> utilities;
vector <Skill *> movement;
};
Unit.h (class A in example)
#pragma once
#include <iostream>
#include <vector>
#include <stdlib.h>
#include <time.h>
using namespace std;
class Skill;
class Unit
{
public:
Skill* skillPtr;
Unit(Skill* skill)
{
skillPtr = skill;
}
void Setup();
string name;
vector <Unit* > heroes;
vector <Unit* > monsters;
};
Hero.h (class B in example)
#pragma once
#include "Unit.h"
class Hero :
public Unit
{
public:
Hero() : Unit(skillPtr)
{
cout << "Pointer: " << skillPtr << endl;
}
};
Main
int main()
{
Skill skill;
Unit unit(&skill);
skill.SetUnit(&unit);
unit.Setup();
return 0;
}

class B: public A {
B() { }
}
When a child class's constructor is called, it first initializes its parent portion by calling a parent constructor. Since you didn't specify one here, the B constructor is trying to call the default A constructor, but one doesn't exist!
To call the constructor you made explicitly, you can do:
class B: public A {
B(): A(Some_C_Pointer) { }
}

Related

Creating an array of pointers of classes in an hierarchy

I have this hierarchy of classes :
B1 B2
\ /
C
How should I make an array of pointers in C++ , in which I can store objects from all the classes?
This is what I tried and is not working:
#include <iostream>
using namespace std;
class MyClass {
public:
void myFunction() {
cout << "Some content in parent class." ;
}
};
class MyOtherClass {
public:
void myOtherFunction() {
cout << "Some content in another class." ;
}
};
class MyChildClass: public MyClass, public MyOtherClass {
};
int main() {
MyChildClass **v=new MyChildClass*[3];
v[1]=new MyClass();
v[2]=new MyOtherClass();
v[1]->myFunction();
return 0;
}
First of all you have to understand, that you can store only pointer to child into pointer to parent and only in that order. Secondly, You may want to use std::variant, so your code will looks like this
#include <iostream>
#include <variant>
using namespace std;
class MyClass {
public:
void myFunction() {
cout << "Some content in parent class." ;
}
};
class MyOtherClass {
public:
void myOtherFunction() {
cout << "Some content in another class." ;
}
};
class MyChildClass: public MyClass, public MyOtherClass {
};
int main() {
std::variant<MyClass*, MyOtherClass*> v[3];
v[1]=new MyClass();
v[2]=new MyOtherClass();
std::get<MyClass*>(v[1])->myFunction();
std::get<MyOtherClass*>(v[2])->myOtherFunction();
return 0;
}

Vector of Base unique_ptr causes object slicing on emplace_back(new T())

I'm trying to pass a type as a argument to a method that will properly construct and push a object to a vector of unique_ptr, however the created object is always the Base object. This happens when using emplace_back(), the same works fine if I just instantiate the object.
Constructing the object outside the vector works fine, however I'm not sure how to move the pointer to the vector after.
body_parts.hpp
#include <vector>
#include <string>
#include <fmt/core.h>
using namespace std;
namespace uhcr {
class body_part
{
public:
string name = "Generic";
template <class T>
void add_body_part()
{
this->body_parts.emplace_back<T*>(new T());
fmt::print("{}\n", this->body_parts.back()->name);
}
private:
vector<unique_ptr<body_part>> body_parts;
};
class torso : public body_part
{
public:
string name = "Torso";
};
}
character.hpp
#include <string>
#include "components/body_parts.hpp"
using namespace std;
namespace uhcr {
class character : public body_part
{
public:
string name = "Character";
};
}
main.cpp
#define FMT_HEADER_ONLY
#include <memory>
#include <fmt/core.h>
#include "src/character.hpp"
using namespace fmt;
using namespace uhcr;
void create_human() {
character human;
human.add_body_part<torso>();
}
int main(void) {
create_human();
return 1;
}
The error is at add_body_part(), when running this code it prints "Generic".
You have multiple data members named name in your subclasses. You probably want to assign values to the member in body_part, not declare new members that shadow it.
class body_part
{
public:
body_part() = default;
string name = "Generic";
template <class T>
void add_body_part()
{
this->body_parts.emplace_back<T*>(new T());
fmt::print("{}\n", this->body_parts.back()->name);
}
protected:
body_part(std::string name) : name(name) {}
private:
vector<unique_ptr<body_part>> body_parts;
};
class torso : public body_part
{
public:
torso() : body_part("Torso") {}
};
class character : public body_part
{
public:
character() : body_part("Character") {}
};
There is no slicing in your code. You seem to expect virtual member variables, but there is no such thing. You get expected output when you use virtual methods:
#include <memory>
#include <vector>
#include <iostream>
#include <string>
using namespace std;
class body_part
{
public:
virtual std::string getName() { return "Generic";}
template <class T>
void add_body_part()
{
this->body_parts.emplace_back<T*>(new T());
std::cout << this->body_parts.back()->getName();
}
virtual ~body_part() = default;
private:
vector<unique_ptr<body_part>> body_parts;
};
class torso : public body_part
{
public:
std::string getName() override { return "Torso"; }
};
class character : public body_part
{
public:
std::string getName() override { return "Character"; }
};
void create_human() {
character human;
human.add_body_part<torso>();
}
int main(void) {
create_human();
return 1;
}
Live Demo
This is a much simpler example of the same effect:
#include <iostream>
#include <string>
struct foo {
std::string name = "Generic";
void x(foo& f){
std::cout << f.name;
}
virtual ~foo() = default;
};
struct bar : foo {
std::string name = "Beneric";
};
int main () {
foo f;
bar b;
f.x(b);
}
bar has two name members. In foo when you write std::cout << f.name it refers to foo::name not to bar::name. You can access bar::name also in foo provided the foo is acutally a bar, but that would lead to some backwards design:
#include <iostream>
#include <string>
struct foo {
std::string name = "Generic";
void x(foo& f);
virtual ~foo() = default;
};
struct bar : foo {
std::string name = "Beneric";
};
void foo::x(foo& f) {
std::cout << dynamic_cast<bar&>(f).name;
}
int main () {
foo f;
bar b;
f.x(b);
}
In your example the dynamic_cast would be less of an issue, as you just created a T and you know it is a T, but nevertheless you should use virtual methods rather than relying on casts.

Threading and Polymorphism

#include<iostream>
#include <thread>
#include <algorithm>
#include <vector>
#include <functional>
using namespace std;
class base
{
public:
virtual void fun_1() { cout << "base-1\n"; }
virtual void fun_2() { cout << "base-2\n"; }
};
class derived : public base
{
public:
void fun_1() { cout << "derived-1\n"; }
void fun_2() { cout << "derived-2\n";
}
};
class caller
{
private:
base *p;
derived obj1;
p = &obj1;
public:
void me()
{
std::thread t(std::bind(&base::fun_2, p), this);
t.join();
}
};
int main()
{
caller c;
c.me();
return 0;
}
I have a written a very simple threading and polymorphism example. All I wanted to do is to call a derived function from a different class which is containing that another class object. The program fails to compile with the message p does not name a type which I could not understand why.
Your error is in line:
p = &obj1;
It is better to write like this, it should help:
class caller
{
private:
derived obj1;
base *p = &obj1;
......
};
or initialize pointer in costructor:
class caller
{
private:
derived obj1;
base *p = nullptr;
caller() : p(&obj1) {}
......
};

c++, Base class constructor seperate declearation and implementation

In my C++ program I have separate .h and .cpp files and everything is working so far except when I want to use a base class constructor for a derived class. It is working but only if I put the function definition if the class deceleration.
Here's the working code for the .h file.
#include <iostream>
using namespace std;
class property
{
public:
property();
property(const property & src);
property(int src);
~property();
virtual int disp() const = 0;
int get_ownable();
private:
protected:
int ownable;
};
class rr : public property
{
public:
rr();
rr(const rr & src);
rr(int src):property(src)
{cout << "\nderived class was called\n";};
~rr();
virtual int disp() const;
private:
protected:
};
The imp.cpp (implementation) file is
#include "head.h"
#include <iostream>
using namespace std;
//property class implimentations
property::property()
{
ownable = 0;
}
property::property(const property & src)
{
ownable = src.ownable;
}
property::property(int src)
{
ownable = src;
cout << "\nparent class called\n";
}
property::~property()
{
}
int property::get_ownable()
{
return ownable;
}
rr::rr()
{}
rr::rr(const rr & src)
{
ownable = src.ownable;
}
/*
rr::rr(int src):property(src)
{
cout << "\nderived class was called\n";
}
*/
rr::~rr()
{
}
int rr::disp() const
{
}
There is other code but it is working fine and not connected to this. The output is
parent class called
derived class was called
So that works just fine but if I un-comment out the function in the .imp file and remove the declaration in the .h
rr(int src):property(src);
I get the error
head.h: IN constructor 'rr::rr(int)':
head.h 113: error: expeted '{' at end of input
imp.cpp: at global scope:
imp.cpp:348:error: redefiniton of 'rr::rr(int);
head.h.113: error: 'rr::rr(int); previousle defined here
All the examples I can find on line of how to do this do it with all the functions defined in the class declaration. I can't find any examples of how to do it with 2 files. Can anyone tell me how to define the base class constructor call in a separate file?
I am on a Linux system using g++ compiler.
Like this
BaseClass.h
#pragma once
class BaseClass {
public:
BaseClass(int a);
private:
int a_private;
};
BaseClass.cpp
#include "BaseClass.h"
#include <iostream>
using std::cout;
using std::endl;
BaseClass::BaseClass(int a) {
cout << "Base class constructor called" << endl;
this->a_private = a;
}
Derived.h
#pragma once
#include "BaseClass.h"
class Derived : public BaseClass {
public:
Derived(int a);
private:
int a_private;
};
Derived.cpp
#include "Derived.h"
#include <iostream>
using std::cout;
using std::endl;
Derived::Derived(int a) : BaseClass(a) {
cout << "Derived class constructor called" << endl;
this->a_private = a;
}
main.cpp
#include "BaseClass.h"
#include "Derived.h"
int main() {
Derived d(2);
return 0;
}
Compiling with the command
g++ main.cpp Derived.cpp BaseClass.cpp and running will result in the following output
Base class constructor called
Derived class constructor called
As mentioned in the comments (credits #IgorTandetnik), initializer lists should be used only in the implementation file. Not in the header file (provided the class is not templated).

Can you create a std::map of inherited classes?

I'm wondering if it's possible to create a map of pointers of inherited classes. Here's an example of what I'm trying to do:
#include <string>
#include <map>
using namespace std;
class BaseClass
{
string s;
};
class Derived1 : public BaseClass
{
int i;
};
class Derived2 : public Derived1
{
float f;
};
// Here's what I was trying, but isn't working
template<class myClass>
map<string, myClass>m;
int main()
{
// Add BaseClasses, Derived1's, and/or Derived2's to m here
return 0;
}
The errors I get are:
main.cpp(23): error C2133: 'm' : unknown size
main.cpp(23): error C2998: 'std::map<std::string,myClass>m' : cannot be a template definition
I get why I'm getting this error, but I'm wondering if it's possible to create a map that can hold different levels of inherited classes? If not, is it possible to create some sort of management system that can hold various class types? Or would I have to make different maps/vectors/arrays/etc. for each type of class?
Yes you can store inherited classes in map, but pointers to them, not objects themselves. Here's a short example (it lacks memory management on pointers)
#include <iostream>
#include <string>
#include <map>
#include <utility>
using namespace std;
class BaseClass
{
string s;
public:
BaseClass() { s = "BaseClass";}
virtual void print()
{
cout << s << std::endl;
}
};
class Derived1 : public BaseClass
{
int i;
public:
Derived1() { i = 10; }
void print()
{
cout << i << std::endl;
}
};
class Derived2 : public Derived1
{
float f;
public:
Derived2() { f = 4.3;}
void print()
{
cout << f << std::endl;
}
};
int main()
{
map<string, BaseClass*>m;
m.insert(make_pair("base", new BaseClass()));
m.insert(make_pair("d1", new Derived1()));
m.insert(make_pair("d2", new Derived2()));
m["base"]->print();
m["d1"]->print();
m["d2"]->print();
return 0;
}
First things first:
template<class myClas>
map<string, myClass> m;
This is not valid C++ and could only mean something like a template alias, but I believe, that is not what you are looking for.
Storing polymorphic objects in C++ is complicated by slicing (constructing a value of the base type from a value of a derived type). Dynamic polymorphism can only be handled through references or pointers. You could potentially use std::ref or boost::ref for situations in which the map will only be passed down the callstack, but this requires some care. Often, storing pointers to the base is the way to go: std::map<std::string, base*>. Managing deallocation yourself is rather tedious and either std::map<std::string, std::unique_ptr> or std::map<std::string, std::shared_ptr> are preferred, depending if you need shared semantics or not.
Basic example. Someone should replace this with something more meaningful.
#include <memory>
#include <string>
#include <map>
#include <iostream>
class animal
{
public:
virtual ~animal() {};
virtual void make_sound() const = 0;
};
class dog : public animal
{
public:
void make_sound() const { std::cout << "bark" << std::endl; }
};
class bird : public animal
{
public:
void make_sound() const { std::cout << "chirp" << std::endl; }
};
int main()
{
std::map<std::string, std::unique_ptr<animal>> m;
m.insert(std::make_pair("stupid_dog_name", new dog));
m.insert(std::make_pair("stupid_bird_name", new bird));
m["stupid_dog_name"]->make_sound();
return 0;
}
You may have template on classes and functions, but not on instances.
You should stick to the map to BaseClass*'es.
Below is the expansion of solution suggested by anton.
#include <iostream>
#include <string>
#include <map>
#include <utility>
using namespace std;
class BaseClass
{
string s;
public:
BaseClass() { s = "BaseClass";}
virtual ~ BaseClass(){}
virtual void print()=0;
};
class Derived1 : public BaseClass
{
int i;
public:
Derived1() { i = 10; }
void print()
{
cout << i << std::endl;
}
};
class Derived2 : public Derived1
{
float f;
public:
Derived2() { f = 4.3;}
void print()
{
cout << f << std::endl;
}
};
class factory
{
map<string, BaseClass*>m;
BaseClass* obj;
public:
factory()
{
obj=NULL;
}
BaseClass* FindType(string s);
void AddType(string s,BaseClass *obj);
void deleter();
~factory(){cout<<"deleting objects from map"<<endl;
deleter();
}
};
void factory :: AddType(string s,BaseClass* obj)
{
m.insert(make_pair(s,obj ));
}
void factory ::deleter ()
{
for (auto pObj = m.begin( );
pObj != m.end( ); ++pObj) {
delete pObj->second;
}
m.clear( );
}
BaseClass* factory::FindType(string s)
{
if(m.find(s)!=m.end())
{
return m[s];
}
return NULL;
}
int main()
{
BaseClass* obj;
factory fact_obj;
fact_obj.AddType("d1",new Derived1());
fact_obj.AddType("d2",new Derived2());
obj=fact_obj.FindType("d1");
if(obj!=NULL)
{
obj->print();
}
obj=fact_obj.FindType("d2");
if(obj!=NULL)
{
obj->print();
}
return 0;
}