C++ Convert static method to simple method - c++

I wrote this.
class A { };
class B : public A
{
public:
static B Convert(const A &a) { return static_cast<const B&>(a); }
};
int main()
{
A a;
B b = B::Convert(a);
}
But I would like to have this, do you know how?
B b = a.Convert();
Thank you in advance for your answers! ^^

Generally I would say, don't do this. Use dynamic_cast<B*>(&a) instead See this post
But if you can check if a is of type B, you could implement it as follows:
class A {
// ...
B& Convert() { return return static_cast<B&>(*this); }
}
BUT be very care full to check if this is even a valid conversion otherwise you might get undefined behaviour during runtime !!!

Related

How to check the type of a template parameter for a polymorphic subclass

I have a class hierarchy in which I<T> and O<T> are a templated classes that extend B (regular class). I aggregates O by means of a pointer, like so:
class B { ... };
template <class T>
class O : public B
{
T getValue() { return value; }
private:
T value;
}
template <class T>
class I : public B
{
T getValue() { return ptr->getValue(); }
void setPtr(O<T>* po) { ptr = po; }
private:
O<T>* ptr;
}
The code above is indeed simplified to show only its bare bones. "Connecting" I and O is done automatically although through user configuration parameters. Because of that, a Singleton table stores polymorphic B pointers to all I and O objects and performs the linking by calling I::setPtr as necessary.
The problem though is that the user can actually mess up and confuse template types of I and O objects, e.g. user can ask to connect an I<int> with an O<float>. E.g.:
O<int>* oi = new O<int>();
O<float>* of = new O<float>();
I<int> ii;
ii.setPtr(oi); /* This is OK. */
O<int>* oi_wrong = static_cast<O<int>*>((B*)of); /* This happens. */
ii.setPtr(oi_wrong); /* This is bad. */
In order to prevent this sort of behaviour, I included a member variable in both I and O that stores typeid(T).name(), thus allowing to check whether the template parameter is actually the same.
Is there a better way?
EDIT: Would there be a better way to do the casting here? Is it not a good idea to store and work with polymorphic pointers in this case?
There's really nothing much you can do if your user is going out of the way to misuse your interface - you should (reasonably) design your code without assuming that your user is going to use static_cast and reinterpret_cast liberally.
In your case, I wouldn't add any additional code/checks. Just assume that your user acts in a reasonable manner.
If you really want, you could use assert and dynamic_cast to check if the passed pointer is actually what you expected in DEBUG builds:
struct A { virtual ~A() { } };
struct B : A { };
struct C : A { };
void setPtr(A* po)
{
assert(dynamic_cast<C*>(po) != nullptr);
}
int main()
{
B b;
setPtr((C*)&b); // might trigger assertion
}
But I strongly suggest against it, as this is overkill.
How about using a friend function for setPtr(), so the user is forced to input fitting types for I and O:
class B { };
template <typename T>
class O : public B
{
public:
T getValue() { return value; }
void setPtr(I<T>& ref_i) { ref_i.ptr = this; };
private:
T value;
};
template <typename T>
class I : public B
{
public:
T getValue() { return ptr->getValue(); }
friend void O::setPtr(I<T>& ref_i)
private:
O<T>* ptr;
};
int main()
{
O<int>* oi = new O<int>();
O<float>* of = new O<float>();
I<int> ii;
of->setPtr(ii); /* This fails. */
O<int>* oi_wrong = static_cast<O<int>*>((B*)of); /* This CAN happen. */
oi->setPtr(ii); /* This is OK. */
}

A function overload depending on enum

Sorry for the noob question, but I cannot seem to get my head around C++'s static nature. The problem: I have a class that returns an enum and depending on it I have to convert the said class using another class and return a vector. In code:
enum TYPES { TYPE_A, TYPE_B, TYPE C }
class A {
TYPES getType() {}
}
class B : public A {}
class C : public A {}
class D : public A {}
std::vector<?> convert_to_vector(const A& a) {
// depending on what enum is returned by a.getType()
// I have to convert a into B, C, or D class and return std::vector of
// an appropriate type, e.g. int for B, float for C, etc.
}
int main() {
A a;
auto v = convert_to_vector(a);
}
The simplest way would be using switch(a.getType()) but I have different return types in each case and using auto as the return type doesn't work. I have tried templates and template specification, but they don't accept the runtime variable that is return by a.getType(). I guess there must be some simple solution that I'm overlooking here, but I have run out of ideas at this point and would be grateful for any pointers.
Thanks!
You can't change the return type of a C++ function at runtime. But you can use a variant type:
std::variant<std::vector<int>, std::vector<float>> convert_to_vector(const A& a) {
if (a.getType() == TYPE_B)
return std::vector<int>();
if (a.getType() == TYPE_C)
return std::vector<float>();
throw std::logic_error("unsupported type");
}
If you don't have C++17, you can use boost::variant instead of std::variant.
I think instead of deciding the type of a vector on an enum a much better solution would be to have a parent class A which can have a vector inside it which is based on a template variable. In your classes B, C, D you can simply inherit A and specify a template type. So, when you create a new object for B, C, D you will already have a vector member for those objects. You can also have a virtual function convertToVec which you can override in the child classes depending on how you want to convert data into a vector.
template<class T>
class A {
std::vector<T> vec;
std::vector<T> GetVector() { return vec; }
virtual convertToVec() { .... }
}
class B : public A<bool> {}
class C : public A<float> {}
class D : public A<long long int> {}
int main() {
B b;
b.GetVector();
//A* b = new B();
//b->convertToVec();
}
While it's pretty hard to follow what exactly you are trying to achieve here, going to use switch-case is not a good idea, instead you'd better to leverage polymorphism. For example:
class A {
public:
virtual void convertToVector(AuxVectorConverter& aux) = 0;
};
class B {
public:
// Add here specific implementation
virtual void convertToVector(AuxVectorConverter& aux) {
aux.convertToVectorB(this);
}
};
class C {
public:
// Add here specific implementation
virtual void convertToVector(AuxVectorConverter& aux) {
aux.doSomethingC(this);
}
};
// Aux class
class AuxVectorConverter {
public:
convertToVector(A* a) {
a->convertToVector(this);
}
convertToVectorB(B* b) {
// Do code specific for B
}
convertToVectorC(C* c) {
// Do code specific for B
}
}
int main() {
AuxVectorConverter* aux;
A* a = ...; // Initialize here either with instance of B or C
// Now, based on run time aux class will issue appropriate method.
aux.convertToVector(a);
}
You might find more details here
UPDATE (Based on comment)
An alternative approach could be to define a map from TYPES to some abstract class which will align with the patter from above, e.g.:
// Map has to be initialized with proper implementation
// of action according to type
map<Types, AbstracatAction> actions;
// Latter in the code you can do:
aux.convertToVector(actions[a->getType()]);
And action will be defined pretty similar to hierarchy I've showed above, e.g.
class AbstractAction {
public:
virtual void convertToVector(AuxVectorConverter& aux) = 0;
};
class ActionB: public AbstractAction {
public:
virtual void convertToVector(AuxVectorConverter& aux) {
aux.covertToVectorB(this);
}
};

Accessing Variable of an Instanced Class

Firstly, I apologize for the bad title naming sense. I am unsure as to how to phrase it correctly.
My problem is that I have four given classes, which I call A, B, C and D for simplicity.
D is a large class containing lots of data.
C is basically a table containing many Ds.
B is a singleton and provides A with an instance of it. B has a member, C* c.
A contains a method which calls B to do something.
I want to test that D has the correct information stored in it, passed through to the program via A.
Here is a simplified version of my code that illustrates the setup.
#include <stdexcept>
#include <string>
#include <vector>
class D {
public:
// Greatly simplified; this class holds much more data in reality.
std::string info {};
};
class C {
private:
std::vector<D*> d {};
public:
D* getD(int dNum) {
return this->d.at(dNum);
}
};
class B {
private:
C* c {};
D* d {};
B() {
this->c = new C();
}
~B() {
delete this->c;
}
B(const B&) = delete;
B& operator=(const B&) = delete;
public:
static B* getInstance() {
static B instance {}; // singleton
return &instance;
}
bool doSomething(const std::string& text) {
int dNum = std::stoi(text); // simplified
try {
this->d = this->c->getD(dNum);
this->d->info += text;
return true;
} catch (const std::out_of_range&) {
return false;
}
}
};
class A {
public:
bool someFunction(const std::string& text) {
return B::getInstance()->doSomething(text);
}
};
My test should somehow look like this.
void test() {
std::string testString {"1"};
A a {};
a.someFunction(testString);
// How can I test that for the 'D' object 'd', that was manipulated by the
// call to 'someFunction', 'd.info == testString'?
}
I have taken a look at stubs and mocks, but I do not understand how to use them in this situation (I have actually never used them).
Once again, sorry if my explanation isn't clear. I am very weak at C++, and thus do not really know how to explain things. As such, even searching for similar questions proved to be impossible, so I apologize if this question has been asked before.
Edit: I do know that I can do this by implementing some getter methods in B to obtain C, but I was hoping for another method.
You have not shown whether you are allocating memory to the class pointers. In a->someFunction(testString);, where does a point to? Then, in class B, neededD = c->getD(dNum); where does c point to? Also, you must change the line requiredD = d->at(dNum); to requiredD = d.at(dNum);. Please provide complete details to understand the problem better.

How to compare 2 objects' private member?

I have 2 class:
class A
{
int aa;
};
class B
{
int bb;
};
class C
{
public:
bool equal(A& av,B& bv)
{
return (av.aa==bv.bb);
}
};
Of course, class C has compilation error cause of private members' access.
Is there a way to implement that equal() member of class C ?
A good solution might be to provide getters in A and B classes.
This way you keep everything encapsulated.
e.g.
class A
{
int aa;
public:
int GetAA()
{
return aa ;
}
};
This is a great scenario for using friend functions:
// forwarding references to each of the classes
class A;
class B;
class C
{
public:
bool equal(A& av,B& bv);
// notice we cannot implement equal() here,
// because A and B have not been defined yet,
// even though they have been declared.
};
class A
{
private:
int aa;
// Simply register to be a friend of A with our 'C::equal' function,
// so that we can access 'aa'
friend bool C::equal(A&, B&);
};
class B
{
private:
int bb;
// Once again, we register as a friend of C::equal,
// this time to access 'bb'
friend bool C::equal(A&, B&);
};
// finally, now that A and B have been fully defined,
// we can implement our equal method:
bool C::equal(A&av, B&bv)
{
return (av.aa == bv.bb);
}
// Sample Usage
int main()
{
A a = A();
B b = B();
C c = C();
c.equal(a, b);
}
I see questions like this and I ask why. There'a apparently no relationship between class A and class B beyond that they have an int.
The way to make this compile is to make C a friend of A and B, or at least make the equal function in C a friend of A and B (with careful use of forward declarations).
class A;
class B;
class C { static bool equal(A const &, B const &); };
class A { friend bool C::equal(A const &, B const &) };
class B { friend bool C::equal(A const &, B const &) };
bool C::equal(A& const &a, B const &b) { return a.a == b.b; }
Please note the const qualifier as it is unlikely that a comparison operator is meant to alter its input. Moreoever I have made it a static function as it doesn't use any of the members of C - it is completely unrelated. (as per your snippet).
Basically - that's how you do it. But don't do it without a LOT of thought. Just because apples and oranges both have pips, doesn't mean there's a lot of point in comparing the numbers of pips.
You can make the classes friends with each other.
But, as pointed out in comments, that's pretty horrible in most cases. The reason the member is private has to be because outside parties shouldn't access it directly.
So, either add operator==() overloads to A and B that can be used (i.e. an bool A::equal(const B&) const; method), or add accessors to return the value for external comparison.
Form friendship with two classes(c & a , c & b) and then compare.
If they are private and cannot be accessed via any kind of public interface it means conceptually they have nothing in common. so add public getAA getBB and use it to make the comparator between objects. I dislike friendship. A lot.
You could make A and B to be friend of C or add int GetVar() const methods to A and B classes.
Why do you need this?
Combine behaviour with the data.
class C
{
public:
void doSomething()
{
if(aa == bb) {
doThis();
} else
doThat();
}
}
private:
int aa;
int bb;
};
Without commenting on the relevance of the request, or alternatives for the presumed underlying reason, I believe you can compare private members thru Reflection:
FieldInfo AInfo = av.GetType().GetField("aa", BindingFlags.NonPublic | BindingFlags.Instance);
int AValue = (int) AInfo.GetValue(av);
etcetera

Seeing what class an object is

If I have a pointer to a base class A in C++, how would I be able to tell in my code that the pointer is to a derived class B or C?
Assuming the base class A is polymorphic (i.e. it has at least one virtual function), you can use dynamic_cast. Given an A* ap;:
if (B* bp = dynamic_cast<B*>(ap)) {
// the object is a B
}
else if (C* cp = dynamic_cast<C*>(ap)) {
// the object is a C
}
You generally shouldn't need to know:
struct A {
virtual int generate_foo() = 0;
};
struct B : A {
int generate_foo() { return 42; }
};
struct C : A {
i_;
C(int i) : i_(i) { }
int generate_foo() { return i_++; }
};
If you have an A* you (1) know that it has a generate_foo() method, and (2) know that generate_foo() will generate an appropriate foo for whatever object you really do have. In general that should be enough and you should be able to keep track of when you have an A*.
Philosophically, the designers of C++ spent years trying to avoid adding runtime type information because it' too easily used incorrectly. However, they eventually decided that they were on the wrong end of a losing battle and added dynamic_cast and typeinfo(). C++0x will add more.