Changing between user defined classes at runtime in C++ - c++

I have two classes with one extending the other. They both have a method called doSomething() that perform something different. I want to be able to have one pointer that I can switch from class A to class B and have the rest of the code run the same because they each have the same method name. Is this possible and is this the correct way to do it? Also, I'm pretty new to C++ so it could be just a problem with that.
class A {
void doSomething()
{
// does something
}
};
class B: public A {
void doSomething()
{
//does something else
}
};
main()
{
A *ptr = new A;
B *bptr = new B;
// a giant loop
ptr->doSomething();
if(condition)
{
ptr = bptr;
}
}

Two ways I can think of to accomplish this.
Your way is fine (with some small changes) if you already have polymorphic types). (If B is-an A, logically)
class A
{
public:
virtual void f() { /* something */ };
};
class B : public A
{
public:
virtual void f() { /* something else */ };
};
int main()
{
A a;
B b;
A* c = 0;
// based on your condition
c = &a;
c->f();
c = &b;
c->f();
return 0;
}
But what if your types aren't really that closely related? Using inheritance implies a very rigid (is-a, in this case) relationship between your classes. Is a B really an A?
Here's a way to accomplish this for classes that have the same named function, but aren't really of similar types.
template <class T>
void do_f(T& obj)
{
obj.f();
}
class D
{
public:
void f() { /* something */ }
};
class E
{
public:
void f() { /* something else entirely */ }
};
int main()
{
// note, D and E have no relation
D d;
E e;
// based on your condition
do_f(d);
do_f(e);
}

What you are trying to achieve is called polymorphism. In C++, you will need to define a common (possibly abstract) base class C for A and B, make doSomething a virtual function, override it in both A and B, and make pointers of type C*. Here is a good introductory article on the topic.

Related

How to access inherited class attribute from a third class?

The goal of the code structure below is to be able to store pointers to objects of any class inherited from 'A'.
When I run this code, I get 0 written out, but what I'm trying to access is the 'B' object's 'num' value, which is 1. How can I do that?
As far as I know, when you create an inherited class's object, you create an object of the parent class too automatically. So can I somehow access the parent class object from it's child and set it's class member to match?
See minimal reproducible example below.
Update: Virtual functions solved the problem.
#include <iostream>
class A
{
public:
int num;
A()
{
num = 0;
}
};
class B : public A
{
public:
int num;
B()
{
num = 1;
}
};
class C
{
public:
A* ptr_array[2];
C()
{
ptr_array[0] = new B();
}
void print()
{
std::cout << ptr_array[0]->num << std::endl;
}
};
int main()
{
C* object_c = new C();
object_c->print();
return 0;
}
The problem is that you define a member num in A, and another member num in B. So an object of type B has two members called num, and you're leaving it to the compiler to choose which one to use -- which it does, according to logical rules which may be unfamiliar to you.
If you remove the line in num; from the definition of B, the code will work as you intend.
Your array is a red herring. You are only using one pointer. Might just as well have it as a member for the sake of the example.
I suppose you might need something like this (note, untested code).
#include <memory>
#include <iostream>
class A {
public:
A() : m_num(0) {} // use this instead of assignment in the c'tor body
virtual int getNum() { return m_num; } // this is **the** way to use inheritance
virtual ~A() = default; // required
private:
int m_num;
};
class B : public A {
public:
B() : m_otherNum(1) {}
virtual int getNum() { return m_otherNum; } // does something different from A
private:
int m_otherNum; // you could also call it m_num, but for clarity I use a different name
};
class C {
public:
C() : m_a (std::make_unique<B>()) {} // note, use this instead of new B
void print() {
std::cout << m_a->getNum() << std::endl;
}
private:
std::unique_ptr<A> m_a; // note, use this instead of A* m_a;
};
I have no way of knowing if this is really what you need (or you think you need). This is how inheritance is supposed to be used in object-oriented programming. You can use it in various other ways and produce correct (as far as the language definition is concerned) programs. But if this is the case, then (public) inheritance is likely not the best tool for the job.

Register/change method from other class in c++

I wonder what is the proper way to assign/override a method from that of another class. For example, here below classes A and B are not and should not be subclassed, but method "A.foo" is a prototype and should be assinged/set in the initialization of B. That is, "A.foo = B.bar_b" (or C or D etc). (The overall idea is to register a send method of servers (B) with a client (A).)
class A {
public:
virtual void foo(arg argA) {
// empty
};
};
class B {
public:
B(A a) {
a.foo = &B::bar_b;
}
void bar_b(arg argA) {
// do stuff B
};
};
A a;
B b(a);
a.foo(arg) // calls bar_b
It doesn't work that way. There are two ways to answer your question. The first is to use proper overriding:
class A {
public:
virtual void foo() {
// empty
};
};
class B : public A {
public:
void foo() override {
// do stuff B
};
};
B b;
A& b_ref = b;
b_ref.foo(); // calls B::foo
The other way is trying to interpret what you actually want to do. Perhaps you want to swap some implementation at runtime to select what A::foo is actually doing.
You need a B to call a method of the class B. Also B(A a) passes the A by value and the assignment in the constructor wont have any effect on the A you pass. Though, most importantly you cannot dynamically assign member functions. However, you can assign to member variables:
#include <functional>
struct A {
public:
void foo() {
do_foo();
};
std::function<void()> do_foo;
};
class B {
public:
B() = default;
B(A& a) {
a.do_foo = [](){B b; b.bar_b(); };
}
void bar_b() {};
};

С++ abstract return type

I have the following structure of classes:
struct A {
virtual void function() = 0;
};
struct B : A {
void function() override {
// ...implementation...
}
};
struct C {
virtual A a() = 0;
};
struct D : public C {
A a() {
return B{};
}
}
the main idea is: I do not really care what class will be returned from D::a, the only property I want it to have is a function() member-function. So I denoted the return type as the abstract class A which has this property as virtual, and then try to return B object which is derived from A. But this does not work, giving error: invalid abstract return type. Could you please suggest a way to achieve the desired effect in C++?
In C++, you can't do polymorphism with objects, because objects could have different sizes, and in C++ types have value semantics. You can, however, do polymorphism with references, and pointers. So your function could be:
A* a();
// or
A& a();
This does mean that you may have problems with ownership. You can also return a smart pointer instead:
unique_ptr<A> a();
You can't create objects of abstract types, you can create pointers of them. As Ayxan said, you can use also smart pointers, but I suggest you use shared_ptr because it's more comfortable.
Use dynamic_cast to convert B to A.
You forgot to add ; to the end of the third struct.
Here is the correct code:
#include <iostream>
struct A {
virtual void function() = 0;
};
struct B : A {
void function() override {
std::cout << "EEAAAHHHH\n";
}
};
struct C {
virtual A* a() = 0;
};
struct D : public C {
A* a() {
B *a = new B;
A *b = dynamic_cast<A*>(a);
return b;
}
};
int main()
{
D d;
A* a = d.a();
a->function();
return 0;
}
If you compile and run the code, you can see that the output is "EEAAAHHHH".
I'm happy to help you, and I wish you success.

Set a value of a class from another class

I'm trying to set the value of a member of a class from another class using this snippet. Here is a sample of the code I'm trying to make work
class A
{
private:
int a;
public:
A()
{
a = 0;
}
A(int val)
{
a = val;
}
int GetA()
{
return a;
}
void SetA()
{
a = 290;
}
};
class B
{
B(){};
void SetB()
{
A a;
a.SetA();
}
};
int main(){
A a;
B b;
b.SetB();
cout << b.GetA();
}
How can I make this code pint out 290.I currently prints out 0
In SetB your A variable is a temporary that is destroyed when the function returns.
The way it is written in your snippet, your code won't compile, because B has no method GetA(). From your use case (the code in main()), I suspect you either want B to inherit from A:
class B : public A
{
public:
B() {];
void SetB()
{
SetA();
}
};
although that doesn't make too much sense, because in this case you could just call b.SetA() directly. Or, you want an object of type A as a member of B:
class B
{
public:
void SetB()
{
a.SetA();
}
int GetA()
{
return a.GetA();
}
private:
A a;
};
But it's a bit hard to tell from your snippet what you're actually trying to achieve.
Also, you probably want your Get…() methods to be const.
If you;re trying to achieve what I think you're trying to achieve then you're nearly there, it is just that you are creating two versions of A, one on the main stack, and one that is a temporary inside B::SetA()
try passing A as a reference parameter to B, so that there is only one version of A.
void SetB(A& a)
{
a.SetA();
}
then your calling code would be:
A a;
B b;
b.SetB(a);
cout << a.GetA();
Alternatively, pass a in the constructor of B and store A as a reference member in B;

Creating derived class instance using base class instance

I have a base class instance, there is a derived class that inherits from the base class, I want to transform the base instance into derived instance, (if possible without copying anything (maybe sending to the derived class a reference of the base class)) how can I achieve that?
Note: I need this because I'm using factory design pattern which identify the derived class needed to be created using a parameter located in the base instance.
//class A
//class B: public A (pure virtual)
//class C: public B
B BFactory::makeB(A &a) {
int n=a.getN();
if(n==1){
return new C();
}
}
Thanks.
Consider the case of the car.
You can treat a Lamborghini as a car.
You can treat a Yugo as a car.
You can treat a car as a Lamborghini if it is a Lamborghini. In C++ this means a pointer to car that really points to a Lamborghini. In order to get a Lamborghini pointer back out of the car pointer you should use dynamic_cast. If the car does not point to a Lamborghini, dynamic_cast will return NULL. This keeps you from trying to pass off a Yugo as a Lamborghini and blowing the Yugo's engine.
But when the Lamborghini is being treated as a car, it can only do car things. If you copy a Lamborghini into a car, you strip out all Lamborghini-ness forever. It's gone.
Code time!
This, I'm afraid cannot be done:
//class A
//class B: public A (pure virtual)
//class C: public B
B BFactory::makeB(A &a) {
int n=a.getN();
if(n==1){
return new C();
}
}
C is being copied into a B and the B is being returned. B would need a constructor that took a C, but the point is moot. B cannot be instantiated if it's pure virtual. For now we'll ignore the leak that would be new C()
Also can't use a reference for this job, pretty much the same problem, so you're trapped into returning a pointer
B * BFactory::makeB(A &a) {
int n=a.getN();
if(n==1){
return new C();
}
}
Now I'm going to make a suggestion: Build the make function into B and handle the case where A doesn't map to anything recognized by B.
class B: public A
{
public:
virtual ~B(){}
static B * makeB(A & a)
{
switch(a.getN())
{
case 1:
return new C();
}
return NULL;
}
};
But this leads to another recommendation: Why should B know anything? And What is the point of A at this level? Why is A storing build codes for classes two or more steps down the hierarchy? Bad from a maintenance point of view. The point of objects is they know who they are and how to manipulate themselves. Short-circuiting this leads to pain.
class B: public A
{
public:
virtual ~B(){}
virtual B* makeB() = 0;
};
Now B only makes Bs, needs no help from A, and those who extend B are stuck with figuring out how to make themselves--a task they should know better than anyone else. Much safer because there is never any possibility of a code unrecognised by B for a new class.
class C: public B
{
public:
B* makeB()
{
return new C();
}
};
class D: public B
{
public:
B* makeB()
{
return new D();
}
};
Edit: Traditional factory
You're asking for an abstract factory. For that you need nothing. You don't even need a class. You certainly don't need a class A. The goal of this sort of factory is the caller knows nothing about the class. By providing an A, the caller needs to know how to make an A or have another factory that makes an A.
First a bit of set-up in a header file BFactory.h:
#ifndef BFACTORY_H_
#define BFACTORY_H_
#include <exception>
class B
{
public:
virtual ~B(){}
virtual std::string whatAmI() = 0;
protected:
// data members common to all B subclasses
};
enum bType
{
gimmie_a_C,
gimmie_a_D,
gimmie_an_E
};
class BadTypeException: public std::exception
{
public:
const char* what() const noexcept
{
return "Dude! WTF?!?";
}
};
B* BFactory(enum bType type);
#endif /* BFACTORY_H_ */
Here I'm going to deviate from the book way a little. Rather than using an integer to identify the type to be built, I'm going to use an enum. Two reasons: Easier to read and understand gimme_a_C than 1 and generates a compiler error if you try to provide a value that is not enumerated.
enum bType
{
gimmie_a_C,
gimmie_a_D,
gimmie_an_E
};
And an exception to flag stupidity if the enum is updated with new types (gimmie_an_E) but the factory is not.
class BadTypeException: public std::exception
{
public:
const char* what() const noexcept
{
return "Dude! WTF?!?";
}
};
This is all the Factory client needs to see. They don't see C. They don't see D. They have no clue that C and D exist in any way other than the names listed in enum bType. All they ever see is pointers to B.
Now for the implementation BFactory.cpp:
#include "BFactory.h"
class C:public B
{
std::string whatAmI()
{
return "C";
}
};
class D:public B
{
std::string whatAmI()
{
return "D";
}
};
B* BFactory(enum bType type)
{
switch(type)
{
case gimmie_a_C:
return new C();
case gimmie_a_D:
return new C();
default:
throw BadTypeException();
}
}
I'll leave it up to the reader to spot the stupid bug in the above code that makes these error prone and why I don't like them.
And usage, main.cpp:
#include "BFactory.h"
int main()
{
B * temp;
temp = BFactory(gimmie_a_C);
std::cout << temp->whatAmI() << std::endl;
delete temp;
temp = BFactory(gimmie_a_D);
std::cout << temp->whatAmI() << std::endl;
delete temp;
//temp = BFactory(1001); // won't compile
try
{
temp = BFactory(gimmie_an_E); // will compile, throws exception
std::cout << temp->whatAmI() << std::endl;
}
catch(BadTypeException& wtf)
{
std::cerr << wtf.what() << std::endl;
}
}
There is still absolutely no use for or involvement of A. A if it exists, should no nothing about B or the children of B.
These days there is a little improvement we can make so that the pointers are a little safer. unique_ptr allows us to maintain the polymporphic advantages of a pointer to B without the memory management woes.
std::unique_ptr<B> BFactory(enum bType type)
{
switch(type)
{
case gimmie_a_C:
return std::unique_ptr<B>(new C());
case gimmie_a_D:
return std::unique_ptr<B>(new D());
default:
throw BadTypeException();
}
}
and the new main:
int main()
{
std::unique_ptr<B> temp;
temp = BFactory(gimmie_a_C);
std::cout << temp->whatAmI() << std::endl;
temp = BFactory(gimmie_a_D);
std::cout << temp->whatAmI() << std::endl;
}
You might want to define a constructor that takes the base class instance as the argument so you can later use static_cast to convert from the base class to the derived class.
class Derived : public Base
{
public:
Derived(const Base& base) : Base{base} {}
};
int main()
{
Base a;
Derived b = static_cast<Derived>(a);
}
If you want to create a derived class instance using the base class instance then there is some conversion rule between the two, which you can specify explicitly using a derived class constructor.
Although it is impossible to alter the type of an object you still can make instances of base and derived classes share the same data:
#include <memory>
#include <iostream>
class Base
{
protected:
struct CommonData
{
int A;
int B;
};
std::shared_ptr<CommonData> m_data;
public:
Base() : m_data(std::make_shared<CommonData>())
{
m_data->A = 0;
m_data->B = 0;
}
void SetData(Base * source)
{
m_data = source->m_data;
}
int A() const { return m_data->A; }
int B() const { return m_data->B; }
void SetA(int value) { m_data->A = value; }
void SetB(int value) { m_data->B = value; }
};
class Derived : public Base
{
public:
int C;
};
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
Base base;
base.SetA(12);
base.SetB(46);
Derived derived;
derived.SetData(&base);
derived.C = 555;
cout << derived.A() << endl; // 12
cout << derived.C << endl; // 555;
cin.get();
}
A base class should not "know" about how to make its own derived class instances. That is the point of inheritance.
The "is a" relationship of derived classes means that any subclass instance will pass as a base class instance transparently, and you can treat it as one, and by default base class non-virtual methods are called on a base class reference, even if it a derived class instance. Only virtual methods use the derived class method.
In the case of creating a base class instance from a derived class you want to "slice" the instance data (normally a bad thing and normally a mistake).
class A{ // ... A stuff };
class B : A
{ // ... B stuff
A make_A() { return (A) B(*this); } // copy cast to A
};
Under no circumstances try to do this:
class B;
class A { // ...
B make_B() { return B(*this); }
};
That is inverted OO logic. It requires at least 2 scans of the source code, which C++ does not do. It fails.