Lets say I have implemented the following classes
class A
{
public:
virtual void printA()
{
cout << "Hi from A!" << endl;
}
};
class B : public A
{
public:
virtual void printB()
{
cout << "Hi from B!" << endl;
}
};
class C : public B
{
public:
void printC()
{
cout << "Hi from C!" << endl;
}
};
Lets also say I have created a std::vector<A *> vec that contains random amount of objects instantiated from A, B, and C. Now lets say I am forced to iterate through all the objects in vec but only call objects that have the printC() method (i.e C instances). What is the best way to do this?
int main()
{
std::vector<A *> vec;
....
// insert random objects from both A, B and C into vec
....
for(vector<A *>::iterator x = vec.begin();
x != vec.end();
x++)
{
if(dynamic_cast<C *>(*x) != 0) // 1. is this OK?
(*x)->printC();
else
(*x)->printA(); // 2. is this also OK?
}
}
Is 1 Ok? And if so is this the best practice?
Also will 2 cause problems in the case of C instances?
Maybe these are stupid questions, but Im quite new to C++ and how polymorphism works in C++ is very strange to me. Thanks
I think you mean the following
#include <iostream>
#include <vector>
int main()
{
class A
{
public:
virtual ~A() = default;
virtual void print() const
{
std::cout << "Hi from A!" << std::endl;
}
};
class B : public A
{
public:
void print() const
{
std::cout << "Hi from B!" << std::endl;
}
};
class C : public B
{
public:
void print() const
{
std::cout << "Hi from C!" << std::endl;
}
};
std::vector<A *> v = { new A(), new B(), new C() };
for ( A *p : v ) p->print();
return 0;
}
The output is
Hi from A!
Hi from B!
Hi from C!
1 won't work, since *x has type A*, and A doesn't have a printC member. It should be:
if (C * c = dynamic_cast<C *>(*x)) {
c->printC();
}
2 is fine, but doesn't match your description; you say you want to "only call objects that have the printC() method", while this calls printA() on the other objects.
This does seem like an odd design though; you'd usually define a single virtual function, implemented by each class to do the right thing for that class, then call that unconditionally for everything.
Related
I have three classes that each inherit from the other: A is inherited by B is inherited by C. I also have one virtual function in each of these classes. I want to create an A-class pointer holding a C-class object and call the B-class function like so:
class A
{
public:
virtual void doStuff() = 0;
};
class B : public A
{
public:
virtual void doStuff() override;
};
class C : public B
{
public:
void doStuff() override;
};
void B::doStuff()
{
std::cout << "Starting doStuff in B\n";
doStuff();
std::cout << "Ending doStuff in B\n";
}
void C::doStuff()
{
std::cout << "doStuff in C\n";
}
int main()
{
A *pointer = new C();
pointer->B::doStuff(); // This doesn't work
}
If I change my main slightly, I get the correct output:
int main()
{
B *pointer = new C(); // Changed A to B
pointer->B::doStuff();
}
Output
Starting doStuff in B
doStuff in C
Ending doStuff in B
How can I change my original code to use an A-class pointer and preferably only one function name?
The issue is that B::doStuff, which refers to the implementation of doStuff at class B, is not a member of A. If you are sure that the pointer is actually pointing to an instance of B or something derived from B, then you could write the following:
int main()
{
A *pointer = new C();
reinterpret_cast<B*>(pointer)->B::doStuff(); // This should work
}
If you cannot be sure about the instance type, use a dynamic_cast.
A pointer of type A can't know for certain that the B version of doStuff is accessible by default; you need to cast the pointer first.
int main()
{
A *pointer = new C();
if(B *b_ptr = dynamic_cast<B*>(pointer))
b_ptr->B::doStuff(); //Will only be executed if dynamic_cast was successful
}
Also, if you're going to use polymorphism like this, make sure you make A's destructor virtual as well, or cleanup won't behave.
class A
{
public:
virtual void doStuff() = 0;
virtual ~A() noexcept = default;
};
Here is some sample code to show why I want to do this. This code will output syntax similar to XML. Calling the "middle" class's function allows me to surround any derived class with the correct "IdentifiedRegion" tags.
#include <iostream>
#include <string>
#include <vector>
class Region
{
public:
virtual void doStuff(std::string tabs) = 0;
};
class IdentifiedRegion : public Region
{
public:
virtual void doStuff(std::string tabs) override;
};
class CircularRegion : public Region
{
public:
CircularRegion(int latitudeIn, int longitudeIn, int radiusIn) : latitude(latitudeIn), longitude(longitudeIn), radius(radiusIn) {}
void doStuff(std::string tabs) override;
private:
int latitude;
int longitude;
int radius;
};
class CountryRegion : public IdentifiedRegion
{
public:
CountryRegion(int countryCodeIn) : countryCode(countryCodeIn) {}
void doStuff(std::string tabs) override;
private:
int countryCode;
};
class StateRegion : public IdentifiedRegion
{
public:
void doStuff(std::string tabs) override;
StateRegion(std::string abbreviationIn) : abbreviation(abbreviationIn) {}
private:
std::string abbreviation;
};
void IdentifiedRegion::doStuff(std::string tabs)
{
std::cout << tabs << "<IdentifiedRegion>\n";
doStuff(tabs + "\t");
std::cout << tabs << "</IndentifiedRegion>\n";
}
void CircularRegion::doStuff(std::string tabs)
{
std::cout << tabs << "<CircularRegion>\n";
std::cout << tabs << "\t" << "<latitude>" << latitude << "</latitude>\n";
std::cout << tabs << "\t" << "<longitude>" << longitude << "</longitude>\n";
std::cout << tabs << "\t" << "<radius>" << radius << "</radius>\n";
std::cout << tabs << "</CircularRegion>\n";
}
void CountryRegion::doStuff(std::string tabs)
{
std::cout << tabs << "<CountryRegion>\n";
std::cout << tabs << "\t" << "CountryCode>" << std::to_string(countryCode) << "</CountryCode>\n";
std::cout << tabs << "</CountryRegion>\n";
}
void StateRegion::doStuff(std::string tabs)
{
std::cout << tabs << "<StateRegion>\n";
std::cout << tabs << "\t" << "<Abbreviation>" << abbreviation << "</Abbreviation>\n";
std::cout << tabs << "</StateRegion>\n";
}
int main()
{
Region *country = new CountryRegion(12);
Region *state = new StateRegion("WA");
Region *radius = new CircularRegion(10, 20, 30);
reinterpret_cast<IdentifiedRegion*>(country)->IdentifiedRegion::doStuff("");
reinterpret_cast<IdentifiedRegion*>(state)->IdentifiedRegion::doStuff("");
radius->doStuff("");
}
digging some codes, I found a curiously manner to call a method from an instance object which I will show in the example code bellow:
class Example{
public:
void Print(){ std::cout << "Hello World" << std::endl;}
};
int main(){
Example ex;
ex.Example::Print(); // Why use this notation instead of just ex.Print();
return 0;
}
There is any behaviour difference between ex.Example::Print() and the standard way ex.Print()? Why the author' code used the former instead of the latter?
Thanks in advance
The difference is that ex.Example::Print() specifies that you want the version of Print() defined in the class Example. In this particular example, there's no difference. However, consider the following:
#include <iostream>
class One {
int i;
public:
One(int ii) : i(ii) {}
virtual void print() { std::cout << i << std::endl; }
};
class Two : public One {
int j;
public:
Two(int ii, int jj) : One(ii), j(jj) {}
void print() override {
One::print();
std::cout << j << std::endl;
}
};
class Three : public Two {
int k;
public:
Three(int ii, int jj, int kk) : Two(ii, jj), k(kk) {}
void print() override {
Two::print();
std::cout << k << std::endl;
}
};
int main() {
Three four(1, 2, 3);
four.print();
std::cout << std::endl;
four.One::print();
std::cout << std::endl;
four.Two::print();
std::cout << std::endl;
four.Three::print();
std::cout << std::endl;
}
The output will be:
1
2
3
1
1
2
1
2
3
ex.Example::Print(); // Why use this notation instead of just ex.Print();
Given the posted code, that is the same as:
ex.Print();
It will make a difference only if name hiding comes into play and you want to be explicit about calling a particular version of the function.
Ex:
struct Foo
{
void Print() const { std::cout << "Came to Foo::Print()\n"; }
};
struct Bar : Foo
{
void Print() const { std::cout << "Came to Bar::Print()\n"; }
};
int main()
{
Bar b;
b.Print(); // Calls Bar::Print()
b.Foo::Print(); // Calls Foo::Print()
}
That's just the mechanics of how things work. As a design choice, it will be better to use virtual functions:
struct Foo
{
virtual void Print() const { std::cout << "Came to Foo::Print()\n"; }
};
struct Bar : Foo
{
virtual void Print() const { std::cout << "Came to Bar::Print()\n"; }
};
No difference between calling ex.Example::Print() and ex.Print() in this example.
The only use/benefit of this invocation I can think of is with inheritance; You can explicitly call over-ridden method in parent class using this syntax from an instance of derived class.
Is there any way in C++ to collect different types of classes and call their methods?
What I want to do is as below,
template<namespace T>
class A
{
A method_A1(T a)
{
...
}
void method_A2(int aa)
{
...
}
...
};
class B
{
...
};
class C
{
...
};
class D
{
...
};
A<B> *b;
A<C> *c;
A<D> *d;
b -> method_A2(3);
c -> method_A2(5);
In this code object b,c,d they are totally different object, right? Not related.
But I want to bind them with a array, so...
z[0] = b;
z[1] = c;
z[2] = d;
like this.
I found some solutions, however the solutions are only for collecting different types. (using void* arrays or vectors for inherited objects) I also wanna access to their methods.
z[0] -> method_A2(3);
z[1] -> method_A3(5);
like this.
In this case how should I do?
Thanks in advance.
typedef boost::variant<A<B>, A<C>, A<D>> AVariant;
std::array<AVariant, 3> z;
z[0] = *b;
z[1] = *c;
z[2] = *d;
Then you can inspect each element's type if needed, or "visit" them using boost::static_visitor as shown here: http://www.boost.org/doc/libs/release/doc/html/variant.html
Why you don't use inheritance and polymorphisms. I have posted an example of what exactly can be a solution of your problem. See the main function:
#include <iostream>
class weapon {
public:
int fireRate;
int bulletDamage;
int range;
int activeBullet;
public:
virtual void fire(void) {std::cout << "machine " << '\n';}
virtual ~weapon() {std::cout << "destructor is virtual" << '\n';}
};
class machineGun: public weapon {
public:
void fire(void) {std::cout << "machine gun firing" << '\n';}
~machineGun(void) { std::cout << "machine gun destroyed" << '\n';}
};
class flamer: public weapon {
public:
void fire(void) {std::cout << "flamer firing" << '\n';}
~flamer(void) {std::cout << "flamer destroyed" << '\n';}
};
int main(void)
{
const int count = 2;
weapon *weapons[count];
machineGun *a = new machineGun();
flamer *b = new flamer();
weapons[0] = a;
weapons[1] = b;
weapons[0]->fire();
weapons[1]->fire();
delete a;
delete b;
}
If you don't want to change your classes' hierarchy, you can try having an array of callable objects. Something like:
#include <iostream>
#include <functional>
#include <array>
class A
{
public:
void Foo(int a)
{
std::cout << "Foo " << a << std::endl;
}
};
class B
{
public:
void Bar(int a)
{
std::cout << "Bar " << a << std::endl;
}
};
int main()
{
using namespace std::placeholders;
A a;
B b;
auto a_func = std::bind(&A::Foo, a, _1);
auto b_func = std::bind(&B::Bar, b, _1);
std::array<std::function<void(int)>, 2> arr = {
std::bind(&A::Foo, a, _1),
std::bind(&B::Bar, b, _1)
};
arr[0](1);
arr[1](2);
return 0;
}
BTW, this will only work if you use compiler with full C++11 support.
I have problem with passing array of pointers to a function.
Class CTree01 is child of CDecorationObj.
When I use for loop, it's working fine.
Here's my code:
CTree01 *trees01;
int numTree01 = ...;
trees01 = new CTree01[numTree01];
//main loop
for(int i=0;i<numTree01;i++)
{
{
//Everything is working okay here, renders all trees
glPushMatrix();
trees01[i].DrawOnTerrain(camera);
glPopMatrix();
}
}
but since i replaced for with a function, it's not working anymore:
void DrawDecorationType(CDecorationObj* objs, int number, CCamera *camera)
{
int x,z;
for(int i=0;i<number;i++)
{
{
glPushMatrix();
objs[i].DrawOnTerrain(camera);
glPopMatrix();
}
}
}
//main loop
DrawDecoration(trees01, numTree01, camera);
When I do in that function:
objs[0].DrawOnTerrain(camera);
it works, and it crashes only when I render objects with index > 0 so I think it must be problem with parameter passed to the function.
Let me see if I can explain the problem using couple of simple classes.
Let's say you have:
struct Foo
{
char a;
};
struct Bar : Foo
{
char b;
};
sizeof(Foo) is 1 and sizeof(Bar) is 2.
And you create an array of Bar object using:
Bar* barPtr = new Bar[2];
The layout of memory that barPtr points to looks like:
Bar(0) Bar(1)
| |
v v
+---+---+---+---+
| a | b | a | b |
+---+---+---+---+
If you pass that pointer to a function a Foo*, that function will interpret the memory as (since sizeof(Foo) == 1):
Foo(0)
| Foo(1)
| |
v v
+---+---+
| a | a |
+---+---+
As you can see, Foo(1) is not really a Foo object. It is really the Bar sub-object of Bar(0). This can easily lead to undefined behavior. Depending on the kinds of data a base class and a derived class have, it could easily crash your program.
The key point is that a pointer that points to an array of derived class objects cannot be treated as a pointer that points to an array of base class objects.
Very good explanation from R Sahu. It clearly describes why your code isn't working and deserves to be accepted.
So what can you do instead?
As far as I understand you want to pass all your CTree01 to a function in one call and have that function iterate all your CTree01s.
The only way I know is to make the container (i.e. array, vector) holding the base class pointers instead of CTree01.
Something like this:
class A
{
public:
A() { cout << "A constructor" << endl;}
virtual ~A() { cout << "A destructor" << endl;}
void hello() { cout << "Hello from A" << endl;}
};
class B : public A
{
public:
B() { cout << "B constructor" << endl;}
~B() override { cout << "B destructor" << endl;}
};
void f(array<A*,2>& t)
{
for(auto e : t)
{
e->hello();
}
}
int main()
{
array<A*,2> z; // Base class pointer array
z[0]=new B; // but it can still hold pointers to B
z[1]=new B;
f(z);
delete z[0];
delete z[1];
return 0;
}
or using vector instead of array
class A
{
public:
A() { cout << "A constructor" << endl;}
virtual ~A() { cout << "A destructor" << endl;}
void hello() { cout << "Hello from A" << endl;}
};
class B : public A
{
public:
B() { cout << "B constructor" << endl;}
~B() override { cout << "B destructor" << endl;}
};
void f(vector<A*>& t)
{
for(auto e : t)
{
e->hello();
}
}
int main()
{
vector<A*> z;
z.push_back(new B);
z.push_back(new B);
f(z);
delete z[0];
delete z[1];
return 0;
}
The following piece of code gets compiled under g++ 4.6.3 for Linux
#include <iostream>
class A {
public:
int x;
std::string c;
A(int x,std::string c):x(10),c("Hi"){
}
~A(){
std::cout << "Deleting A()" << std::endl;
}
};
class B : public A {
public:
B():A(20,"Hello"){
}
~B(){
std::cout << "Deleting B()" << std::endl;
}
};
int main(){
B o;
std::cout << o.x << std::endl;
std::cout << o.c << std::endl;
return(0);
}
but it does not do what is supposed to do, the type B is not able to change the values of that 2 variables that it inherit from A.
Any explanations about why this doesn't work properly ?
Your base constructor takes those values...and completely disregards them!
Change this:
A(int x,std::string c):x(10),c("Hi"){}
to this:
A(int x,std::string c):x(x),c(c){}
There seems to be some confusion about what you want and how to achieve this.
If I got you right this is what you want:
class A {
public:
int x;
std::string c;
//default initization of A
A():x(10), c("Hi") {}
//initializing the values of A via parameters
A(int x,std::string c):x(x),c(c){}
~A(){
std::cout << "Deleting A()" << std::endl;
}
};
class B : public A {
public:
B():A(20,"Hello"){
}
~B(){
std::cout << "Deleting B()" << std::endl;
}
};
So in this example:
int main()
{
A a;
A a1(2, "foo");
B b;
return 0;
}
a.x == 10, a.c == "Hi"
a1.x == 2, a1.c == "foo"
b.x == 20, b.c == "Hello"
OK, I don't understand what exactly you want and why, but here's a suggestion, with C++11, you can do the following:
struct Base {
int a;
float b;
};
struct Derived: public Base {
Derived(): Base{1,1.0} {}
};
int main() {
Derived d;
}
as long as the base is a POD type.
I'd still prefer A(int x = 10,std::string c = std::string("Hi")):x(x),c(c){...} though.
IMHO, you need to review if you really need that much control over your base class in the first place. You're not really supposed to micro-manage a class from the outside like that, it's an indication of a flaw in your class hierarchy.