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;
}
Related
#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) {}
......
};
This is the simplified version of my code:
#include <iostream>
using namespace std;
class ClassA {
public:
void method1A(){
cout << "Hello World." << endl;
}
void method2A(){
cout << "Bye." << endl;
}
};
class ClassB {
public:
void method1B(){
ClassA objectA;
objectA.method1A();
}
void method2B(){
objectA.method2A();
}
};
int main() {
ClassB objectB;
objectB.method1B();
objectB.method2B();
return 0;
}
The error is: ‘objectA’ was not declared in this scope, I suppose it's because the method "method2B" does not have access to the object "objectA" -yep, I'm learning c++ ^^-. How it works without move the "objectA" object declaration from "method1B"?
You need to declare the member object outside of your methods:
class ClassB {
public:
ClassA objectA;
void method1B(){
objectA.method1A();
}
void method2B(){
objectA.method2A();
}
};
That way it is accessible to everything inside the class. If you do not want it accessible outside of the class, make it private or protected instead:
class ClassB {
public:
// Your public declarations
private:
ClassA objectA;
};
You have two options:
put objectA as a member of ClassB
create another ClassA inside method2B (like you did in method1B)
You could dynamically allocate space for a new ClassA on the heap and then return a pointer to the start of that memory:
#include <iostream>
using namespace std;
class ClassA {
public:
void method1A(){
cout << "Hello World." << endl;
};
void method2A(){
cout << "Bye." << endl;
};
};
class ClassB {
public:
ClassA * method1B(){
ClassA * ObjectA = new ClassA;
ObjectA->method1A();
return ObjectA;
};
void method2B(ClassA * objectA){
objectA->method2A();
};
};
int main() {
ClassB objectB;
ClassA * objectA = objectB.method1B();
objectB.method2B(objectA);
delete objectA;
return 0;
};
I hope this helped.
I'm making an inventory system, and am trying to use derivatives to create different items, so that I can have default elements in the parent and specialized ones in the children.
So what I've written below, at the moment it prints "I'm a parent" but I am trying to get it to print "I'm a kid", and in the lack of a child definition of stuffToSay print "I'm a parent" Thanks!
using namespace std;
class myParent {
public:
virtual void saySomething() {
cout << stuffToSay;
}
string stuffToSay = "I'm a parent";
private:
};
class myDerivitive : public myParent{
public:
myDerivitive() {};
string stuffToSay = "I'm a kid";
private:
};
int main() {
myParent* people[] = {
new myDerivitive()
};
cout << people[0]->stuffToSay;
system("pause");
}
Thats not how it works. The saySomething in parent doesn't know anything about the string in the derived class and member variables aren't virtual.
You can do it e.g. like this
#include <iostream>
#include <string>
struct myParent {
void saySomething() {
cout << getSomething();
}
virtual std::string getSomething(){ return "I'm a parent"; }
virtual ~myParent(){} // virtual destructor is needed
};
struct myDerived : myParent {
virtual std::string getSomething(){ return "I'm the derived"; }
};
int main() {
myParent* p = new myDerived();
p->saySomething();
delete p; // dont forget to delete !!
}
Something like this is normally done using the constructor of your class, the child class has all the variables of its parent class so to do what you are looking for it can be done like this:
using namespace std;
class myParent {
public:
myParent() {
stuffToSay = "I'm a parent"
}
virtual void saySomething() {
cout << stuffToSay;
}
string stuffToSay;
private:
};
class myDerivitive : public myParent{
public:
myDerivitive() {
stuffToSay = "I'm a kid";
};
private:
};
int main() {
myParent* people = new myDerivitive();
cout << people->stuffToSay();
delete people; // Simplified to a single pointer and remember to delete it
people = NULL;
system("pause");
}
Please take a look at this link for more information on classes:
http://www.cplusplus.com/doc/tutorial/classes/
This link will help with the understanding of inheritance, since your derivative class would have the "stuffToSay" variable since its parent had it:
http://www.cplusplus.com/doc/tutorial/inheritance/
There is no such thing as a virtual or overridden variable in C++; that sort of polymorphism only applies to methods. So you could do this:
struct parent {
virtual void saySomething() {
cout << "I'm a parent!\n";
}
};
struct child: parent {
void saySomething() override {
cout << "I'm a child!\n";
}
};
Or you could solve it with something more like your current structure by adding a layer of indirection:
struct parent {
void saySomething() {
cout << thingToSay() << '\n';
}
private:
virtual string thingToSay() { return "I'm a parent!"; }
};
class child: parent {
virtual string thingToSay() { return "I'm a child!"; }
};
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;
}
Take a look at this code:
#include <iostream>
using namespace std;
class A
{
private:
int privatefield;
protected:
int protectedfield;
public:
int publicfield;
};
class B: private A
{
private:
A a;
public:
void test()
{
cout << this->publicfield << this->protectedfield << endl;
}
void test2()
{
cout << a.publicfield << a.protectedfield << endl;
}
};
int main()
{
B b;
b.test();
b.test2();
return 0;
}
B has access to this->protectedfield but hasn't to a.protectedfield. Why? Yet B is subclass of A.
B has access only to the protected fields in itself or other objects of type B (or possibly derived from B, if it sees them as B-s).
B does not have access to the protected fields of any other unrelated objects in the same inheritance tree.
An Apple has no right to access the internals of an Orange, even if they are both Fruits.
class Fruit
{
protected: int sweetness;
};
class Apple: public Fruit
{
public: Apple() { this->sweetness = 100; }
};
class Orange: public Fruit
{
public:
void evil_function(Fruit& f)
{
f.sweetness = -100; //doesn't compile!!
}
};
int main()
{
Apple apple;
Orange orange;
orange.evil_function(apple);
}
this->protectedfield:
B enherits of A, this means protectedfield is a property of itself now, so it is able to access it.
a.protectedfield:
a is a member of class B, this member has the protectedfield variable which is protected. B cannot touch it, because protected means only access from A within.
Lets break the whole code in small parts.Copy and paste this two code and try to compile!!!!
#include <iostream>
using namespace std;
class A
{
private:
int privatefield;
protected:
int protectedfield;
public:
int publicfield;
};
int main()
{
A a;
cout<<a.publicfield;
cout<<a.privatefield;/////not possible ! private data can not be seen by an object of that class
cout<<a.protectedfield;////again not possible. protected data is like privete data except it can be inherited by another.If inherited as private then they are private,if as protected then protected and if as public then also protected.
}
Now B inherits class A as private
#include <iostream>
using namespace std;
class A
{
private:
int privatefield;
protected:
int protectedfield;
public:
int publicfield;
};
class B: private A
{
private:
A a;
public:
void test()
{
cout << this->publicfield << this->protectedfield << endl;
}
void test2()
{
cout << a.publicfield << endl;
}
};
int main()
{
/*Now B will have both public and protected data as private!!!!
That means
B now looks like this class
Class B
{
private:
int protectedfield;
int publicfield;
}
As we have discussed private/protected data can not be accessed by object of the class
so you you can not do things like this
B b;
b.protectedfield; or b.publicfield;
*/
B b;
b.privatefield;////Error !!!
b.protectedfield/////error!!!!
}
Thanks!