Suppose I have three classes:
typedef struct base
{
float A;
float B;
...
base() : A(1.0f), B(1.0f) {}
} base;
class derived1 : base
{
int C;
int D;
};
class derived2 : base
{
int E;
int F;
};
And I would like to copy base class data from one derived class object to another.
Is it safe to do the following, to only copy the base class values of A, B, etc... from one object to another?
derived1* object1 = new derived1;
derived2* object2 = new derived2;
void make_object1()
{
object1->C = 2;
object1->D = 3;
}
void make_object2()
}
object2->A = 4;
object2->B = 5;
object2->E = 6;
object2->F = 7;
}
void transfer_base()
{
*((base*)object1) = *((base*)object2);
}
Assuming my program would need to do this sort of operation often would there be a better (faster code) way to accomplish this?
The reason that I'd doing this is I have written a simulation and a graphical renderer. I want to update graphical display objects with only select data from objects in the simulation as efficiently as possible. The simulation is extremely CPU intensive...
So far this approach seems to be working however I'm concerned there may be something I'm overlooking...
The code
*((base*)object1) = *((base*)object2);
is quite unsafe, because the C style casts can do just about anything. Such as reinterpretation, or casting away constness.
Instead, if you want to invoke base::operator=, then invoke that explicitly. Excplicit = good, implicit = bad.
I.e.,
object1->base::operator=( *object2 );
This is still not “safe”, because the slicing may break the class invariant of the derived class. And anyone trying to get a handle on what happens in this code may be surprised by the sudden change of values in the base class sub-objects, and waste a lot of time trying to ascertain where those values are coming from. But at least it’s not as bad as the C style casting.
Instead, why not create your own assignment method in the base class (removing the unneeded C-artifact typedeffing):
struct base
{
float A;
float B;
...
base() : A(1.0f), B(1.0f) {}
base& assign_base(const base& right) { A = right.A; B = right.B; }
};
Then you can just say
der1.assign_base(der2);
Related
I try to have an abstract base class act like an interface and instantiate a derived class based on user input. I tried to implement it like this
class A
{
public:
virtual void print() = 0;
};
class B : A
{
public:
void print() override { cout << "foo"; }
};
class C : A
{
public:
void print() override { cout << "bar"; }
};
int main()
{
bool q = getUserInput();
A a = q ? B() : C();
a.print();
}
But that does not work. I’m coming from c# and that would be valid c# so I’m looking for an equivalent way of implement it in c++. Could someone please give me a hint? Thanks!
There are two problems with the code in its current state.
By default in C++, a class that inherits from a class or struct will be private inheritance. E.g. when you say class B : A, it's the same as writing class B : private A -- which in C++ restricts the visibility of this relationship only to B and A.
This is important because it means that you simply cannot upcast to an A from outside the context of these classes.
You are trying to upcast an object rather than a pointer or reference to an object. This fundamentally cannot work with abstract classes and will yield a compile-error even if the code was well formed.
If the base class weren't abstract, then this would succeed -- but would perform object slicing which prevents the virtual dispatch that you would expect (e.g. it won't behave polymorphically, and any data from the derived class is not present in the base class).
To fix this, you need to change the inheritance to explicitly be public, and you should be using either pointers or references for the dynamic dispatch. For example:
class A
{
public:
virtual void print() = 0;
};
class B : public A
// ^~~~~~
{
public:
void print() override { cout << "foo"; }
};
class C : public A
// ^~~~~~
{
public:
void print() override { cout << "bar"; }
};
To model something closer to the likes of C#, you will want to construct a new object. With the change above to public, it should be possible to use std::unique_ptr (for unique ownership) or std::shared_ptr (for shared ownership).
After this, you can simply do:
int main() {
auto a = std::unique_ptr<A>{nullptr};
auto q = getUserInput();
if (q) { // Note: ternary doesn't work here
a = std::make_unique<B>();
} else {
a = std::make_unique<C>();
}
}
However, note that when owning pointers from an abstract base class, you will always want to have a virtual destructor -- otherwise you may incur a memory leak:
class A {
public:
...
virtual ~A() = default;
};
You can also do something similar with references if you don't want to use heap memory -- at which point the semantics will change a little bit.
References in C++ can only refer to an object that already has a lifetime (e.g. has been constructed), and can't refer to a temporary. This means that you'd have to have instances of B and C to choose from, such as:
int main() {
auto b = B{};
auto c = C{};
bool q = getUserInput();
A& a = q ? b : c;
a.print(); // A& references either 'b' or 'c'
}
You need to use pointers :
A* a = q ? static_cast<A*>(new B) : new C;
...
delete a;
A ternary is also a special case here, as it takes the type of the first expression.
If C inherited from B here it would not be a problem.
I have a super Class (A) and two sub Class (B ,C)
an abstract Function in A have two difference return type in B and C!
How i have to Declare these??
return type is important
class A { //Super Class
public:
A();
virtual (some Type) QWERTY() = 0;
};
class B : public A { //Sub Class
public:
B();
double QWERTY();
};
class C : public A { //Sub Class
public:
C();
unsigned int QWERTY();
};
i'v to call sub Class function with super Class pointer
Since the functions are different in each sub-classes, you'll have to access them from pointers to those sub-classes.
This is exactly the kind of situation where dynamic_cast<> can help: it can conditionally convert a pointer from a base class to a sub-class if and only if it happens to be of the correct type:
void foo(A* a_ptr) {
B* b_ptr = dynamic_cast<B*>(a_ptr);
C* c_ptr = dynamic_cast<C*>(a_ptr);
if(b_ptr) {
b_ptr->QWERTY();
}
if(c_ptr) {
c_ptr->QWERTY();
}
}
It's, however, worth mentioning that this is some pretty ugly code, and might be suitable to solve the quiz you are presenting us, but in a normal environment, there are some design reevaluation that would happen before going to implement things this way.
Okay, so to illustrate the issue I am having I will show some (pseudo) code.
Lets say I have the following models:
class Animal : public GameObject;
class Player : public GameObject;
class GameObject : public ObjectInterface;
class ObjectInterface
{
public:
virtual ~ObjectInterface() = default;
virtual vec3 GetPosition() = 0;
}
Now I also hold some "object context", which holds collections of certain game objects.
class ContextObject
{
// they implement ObjectInterface
vector<shared_ptr<Animal>> animals;
vector<shared_ptr<Player>> players;
}
Now I have a TargetSelector class, which works directly with the ObjectInterface only.
class TargetSelector
{
// this is somehow not possible, although `animals` are a subclass of `ObjectInterface`
vector<shared_ptr<Model::ObjectInterface>>& GetAvailableTargets()
{
return context->animals; // context is some `ObjectContext`
}
}
I would expect the above code to work, since an Animal is of the type ObjectInterface. But instead I get an error saying it cannot convert from an vector<shared_ptr<Animal>> to an vector<shared_ptr<ObjectInterface>>. Is this even suppose to work?
Could someone explain me why I cannot do this kind of polymorphism and if possible a nice solution so I can make this work.
Thanks, any help is appreciated!
I would expect the above code to work, since an Animal is of the type ObjectInterface.
Unfortunately, class templates don't work that way.
Given
struct Base {};
struct Derived : Base {};
Derived d;
Base& bref = d; // OK.
Base b = d; // OK.
However, given
template <tpename T> Foo {};
Foo<Derived> d;
Foo<Base>& bref = d; // Not OK
Foo<Base> b = d; // Not OK.
Derived is a sub-type of Base does not imply Foo<Derived> is a sub-type of Foo<Base>.
That analogy applies to shared_ptr too. Your problem is compounded by use of another layer of class template. shared_ptr<Derived> is not a sub-type of shared_ptr<Base>. Never mind being able to use vector<shared_ptr<Derived>> when a vector<shared_ptr<Base>> is exepcted.
You can use vector<shared_ptr<ObjectInterface>> in all the places and make sure to cast to the appropriate shared_ptr type before using it.
Check out the various pointer_cast functions at http://en.cppreference.com/w/cpp/memory/shared_ptr/pointer_cast.
I need to make an array of 100 pointers to objects of two classes that are derived from an abstract class.
First element of array is of class B, second is C, third is B etc.
A is base and abstract class at the same time.
For example:
class A
{
public:
A();
virtual double pureVirtualMethod() = 0;
};
class B: public A
{
};
class C: public A
{
};
In main() I need to make an array of pointers that will point to any of the derived classes.
I can't use Stl or Boost.
The comments are right. You can google the answer in 5 seconds.
In any case...
You need to define the body of the constructor for A, or remove the declaration and use the default one
Up to you to delete the array to avoid a memory leak :)
class A
{
public:
A() {} // <----- ADDED BODY
virtual double pureVirtualMethod() = 0;
};
int main()
{
A* names[100];
for (int i = 0; i < 100; ++i)
if (i % 2)
names[i] = new C();
else
names[i] = new B();
}
Since there isn't a question: make sure your base class has a virtual destructor. Without a virtual destructor you won't be able to easily delete the objects. To maintain the objects I would create a simple version of std::unique_ptr if I have to write it myself (well, for my own standard library implementation I, obviously, have an implementation anyway which I'd think I should be able to use...).
I just cannot imaginate a way to do a call to a function with genericity. I have a code which a have to call a function in two different classes in different moments.
I have A and B classes which I can access one time or other time. Or I access A or I access B. Not both in the same type.
I have code this program but I just cannot imagine how to do this. Or if this is good for performance or codding. I just want to eliminate the C class but I don't know how.
Any idea?
class MyClass
{
public:
MyClass() {} //contructor padrão, não deve ser utilizado isoladamente
virtual int a() = 0;
virtual int b() = 0;
int c()
{
return b();
}
};
class A : public MyClass
{
public:
int a() { return 1; }
int b() { return 1; }
int d() { return 1; }
};
class B : public MyClass
{
public:
int a() { return 1; }
int b() { return 1; }
int e() { return 1; }
};
class C
{
public:
A ca;
B cb;
enum TIPO { A, B };
TIPO Tipo;
C(TIPO tipo) { Tipo = tipo; }
int a()
{
switch(Tipo)
{
case A:
return ca.a();
break;
case B:
return cb.b();
break;
default:
break;
}
}
};
void main()
{
C c(C::B);
c.a();
return;
}
If I understand you correctly, you are trying to eliminate the members (ca,cb), and just call the appropriate base class method.
If that's the case, it can be done by using:
switch(Tipo) {
case A:
return A::a();
case B:
return B::a();
}
However, I would recommend revisiting your design. Typically, situations like this can often be handled by rethinking/reworking the class design so that there is a single base class or interface which defines a(), and instead of creating one concrete class with 2 base classes, create one of two specific, concrete classes derived from a single base class. There is no need for multiple inheritance here. (This is especially true since you know the type at construction time.)
As you've written 'A' and 'B', you don't actually need the C class. By declaring your member functions "virtual" you are using run time polymorphism and this will result in the "correct" functions being called:
void foo (MyClass & mc) {
mc.a ();
}
int main () {
A a;
B b;
foo (a); // 'mc.a()' will call 'A::a'
foo (b); // 'mc.a()' will call 'B::a'
}
Is there some other reason that you need to inherit from C?
First of all, decide if your A and B classes will belong to C by inheritance or by composition. Right now you're doing both, which is both bloating your code and making it confusing.
If you do go for inheritance, then you have another problem: similarly named overridden methods, a prime cause for the Deadly Diamond of Death. Multiple inheritance, in case you haven't heard, is evil. Avoid it unless there is no other way to get the job done.
If you go with composition (my recommendation), then it seems to me that your specification of "not at the same time" becomes unnecessary. You're not accessing the same data, so there's no possibility of a race condition. And if you are (for some ungodly reason) determined to access the same memory space, then you'll need to brush up on multithreading, the implementation of which will differ with each platform you develop on.
Ok, I guess you want C::a() to call A::a() or B::b() depending on what "type" or "mode" C has. First of all there is no need to let C inherit A and B.
class C
{
private:
A ca;
B cb;
enum TIPO { A, B };
TIPO Tipo;
public:
SetTipo(TIPO tipo) { Tipo = tipo; }
// ..
};
void main()
{
C c(C::B); // Start with mode B and call B::b()
c.a();
c.SetTipo(C::A); // Now I'm in mode A .. call A::a()
c.a();
return;
}
This assumes that C really should own one instance of A and one instance of B and I'm not sure if that's what you want. Your question didn't state if that's the case or not.
Cheers
This question is very unclear. I have another interpretation of the question, along with an answer.
Interpretation: given:
class C {
public:
int a();
int b();
};
You want to call either method a() or method b(), selectable at runtime. Solution: member function pointers.
A member function pointer is like a regular C function pointer, except that it applies to a method in a class, and its type signature includes the name of the class it's invoked on. Here's how to use one with the class I've just given:
typedef int (C::*SELECT_FUNC)(void);
This is the declaration of the member function pointer. It is similar to the declaration of a regular C function pointer, with the addition of a class name. Now we can assign it:
SELECT_FUNC ptr = &C::a;
SELECT_FUNC other_ptr = &C::b;
And to call:
C item;
C *item_ptr;
int rv = item.*ptr();
int rv2 = item_ptr->*other_ptr;
This syntax is funky. Think of the "*" as "dereference". We are dereferencing the member function pointer to get a METHOD, at which point we can invoke the method in what is otherwise the normal way.
The cool thing about this is: it doesn't even matter if the methods are virtual or not. You can assign either a virtual method or a non-virtual method to a member function pointer. If you call a method through a function pointer and the method happens to be virtual, then you'll get a true virtual call (i.e. if the function pointer is declared to point to a base class method, but you use a derived class instance for "this", then the derived class method will be called, just as it is for a normal virtual call.)
I would think through your requirements carefully. Your question is not well asked, which leads me to believe that you do not understand yourself what you really want to achieve. Once you understand what you want to achieve, then either a class hierarchy or member function pointers (or both) may be the best choice to solve your problem.