Given class A and Class B. I need to use the "add" function as shown in the cpp file to store an object reference of class B in an object array of class A.
I should be able to use "->" as shown in the cpp file to call Class B's "print" function.
Compile Time Error: void* is not a pointer-to-object type
So how do I solve this error?
==================================================================================
// header file
// ABC.h
class A{
private:
size_t size_;
void * a_[256];
static int index_;
public:
void add(void * obj);
void * operator[](int x){
return a_[x];
}
};
class B {
private:
const char * f_;
const char * l_;
public:
B(const char * fn, const char * loc ):f_(fn), l_(loc){ A(); };
void print();
};
// cpp file
#include "ABC.h"
int A::index_ = 0;
inline void A::add(void* obj){
void * insertionPoint = static_cast<char *>(a_[index_]) + ( size_ * index_ );
memcpy( insertionPoint, obj, size_);
++index_;
}
inline void B::print(){
...
}
int main()
{
A a;
B b( "Name", "Some string");
a.add( &b );
a[0]->print(); // <-- This should be an object reference to B, but it is producing the error.
return 0;
}
Output:
Name Some string
The following method makes no sense:
virtual void add(A * obj){
*this = dynamic_cast<void*>(obj);
}
in case you want to store pointers to other instances of A within A, create an array of pointers where you will hold them, trying to "replace" the current instance (i.e. *this =...) makes no sense.
Also note that dynamic_cast would make sense if you want to examine whether A* points to instance of B:
A* a = new B();
// in compile time it's A*, but does it really point to instance of B? :
B* b = dynamic_cast<B*>(a);
Why don't you start with something simpler? Let's say:
class A {
public:
virtual void print() { std::cout << "a"; }
};
class B : public A {
public:
void print() /* const */ { std::cout << "b"; }
};
used as:
A* a = new A();
A* b = new B();
a->print();
b->print();
which (as it stands) outputs ab. Then you can change the B's print() to const and realize that the constness of method actually matters.
The solution involved advice from all above comments
Compare the differences between the question and answer to see the solution, fully.
What I needed to do was change class A's private a_ member to type A: A * _a[256]
NEXT: I needed to change the operator[] and the add method's parameter to type A, as well: A * operator[](A * obj)
NEXT: I needed to add a virtual void print()for inheritance purposes to class A.
FINALLY: Class B needed to inherit class A
Below is working code
NOTE: I am not sure if this code is entirely secure or deals with memory issues properly, but I do know that it prints to output what it was intended to print.
==================================================================================
// header file
// ABC.h
class A{
private:
size_t size_;
A * a_[256];
static int index_;
public:
void add(A * obj);
A * operator[](int x); // Any subclass object reference of A can be assigned now.
virtual void print()const; // Virtual tells the compiler to look for other void print methods first.
};
class B : public A{
private:
const char * f_;
const char * l_;
public:
B(const char * fn, const char * loc ):f_(fn), l_(loc){ A(); };
void print()const;
};
// cpp file
#include "ABC.h"
int A::index_ = 0; // Need to call this here because it is declared static in Class A and can be used dynamically.
inline A * A::operator[](int x){
return a_[x]; // Implements operator[], so class A can act like a container.
}
inline void A::add(A* obj){
a_[index_] = obj; // Adds a base or subclass object reference to class A object array.
++index_; // Need this to remember current index of object reference A's array.
}
inline void A::print()const{}
inline void B::print()const{
std::cout << "B " << firstname_ << " works in " << location_ << std::endl;
}
int main()
{
A a;
B b( "Name", "Some string");
a.add( &b );
a[0]->print();
return 0;
}
Output:
Name Some string
Related
This is the rough outline of my code. I've left out some details so let me know if you need more context.
class A;
class B;
class C {
public:
C(int dat, int idx) {
data = dat;
i = idx;
}
friend class A;
friend class B;
private:
int data;
int i;
};
class A {
public:
void insert(int dat, int idx) {
c = new C(dat, idx);
// ... other operations to place it
}
// I have the correct destructor, etc..
// function that returns an address to a specific instance of a dynamically allocated C
C* getPointer(int dat) const {
return getPointer(dat); // a call to an internal function
// omitted for simplicity because this works
}
private:
C* c;
};
class B {
public:
B() {
size = 5;
arr = new D[size];
}
// I have the correct destructor, etc..
C* getPtr(int idx) {
return(arr[idx].X);
}
void setPtr(C*& oldPtr, C* newPtr) {
oldPtr = newPtr;
}
private:
struct D{
int d;
C* X;
D() {
d = 0;
X = nullptr;
}
};
D* arr;
int size;
};
int main() {
A a;
B b;
// index is a value returned from an insert function in class B
// dat is a value to find which address should be returned of the objects in class A
a.setPtr(b.getPtr(index), a.getPointer(dat));
return 0;
}
I wrote a function (getPointer(int dat) in class A) that returns the address of an instance of the dynamically allocated object of class C. So, how do I update X to point at this address instead of null?
I've tried many different ways and currently (what I thought was the most promising) was the setPtr() function in class B. It correctly changes the address X is pointing to once, but when I call any other functions its value is back to nullptr.
Any help or advice would be greatly appreciated. Thank you.
You correctly wrote getPtr(int idx) (if I understand your spec. correctly). Now, the return value is C* there, which is not C*& or C**, so it won't be updated if you change the result afterwards - think of it as a return i; won't expose int i; member if return type is int.
So either:
you need to change the return type of getPtr(int idx) and then setPtr() is not really needed;
or you can build both of these in setPtr() as:
void setPtr(int idx, C* newPtr) {
arr[idx].X = newPtr;
}
I have a class like this one:
struct Base
{
void aa(int n) const {
std::cout << "aa() " << field*n << std::endl;
}
void bb(int n) const {
std::cout << "bb() " << field*n*2 << std::endl;
}
int field = 2;
};
I want to be able to select, at compile time, one of the two implementations, aa() or bb(), via a call to an operator method. Something like:
Base data;
Magic obj(data);
obj.as_AA() * 33; // should call data.aa(33)
obj.as_BB() * 44; // should call data.bb(44)
data must not be duplicated. And the choice of aa() vs bb() must be resolved at compile time.
I have a solution which uses a downcasting whose behavior is in theory undefined (I think). It builds (with g++ and clang++) and runs perfectly, but still ...
struct AA : public Base
{
void operator*(int n) const {
return Base::aa(n);
}
};
struct BB : public Base
{
void operator*(int n) const {
return Base::bb(n);
}
};
struct Chooser
{
Base obj;
template<typename WHICH> // will be either AA or BB
const WHICH& as() const {
return static_cast<const WHICH&>( obj ); // downcasting
}
};
In main.cpp:
Chooser ch;
ch.as<AA>() * 5; // prints "aa() 10"
ch.as<BB>() * 7; // prints "bb() 28"
How unreliable is my solution? (because of the downcasting which is technically undefined)
Do you see alternatives?
Thanks
ps: of course I could trivially use
Base data;
data.aa(33);
data.bb(44);
but I really want to access the different implementations via the same name, ie., the operator*
I could also use a templated operator* in Base and have explicit template specializations, however that would force me to use an ugly syntax, which kind of voids the purpose of the operator:
struct Base {
\\...
template<int N> void operator*(int n) const;
};
template<> void Base::operator*<1>(int n) const {
aa(n);
}
Which requires:
Base data;
data.operator*<1>(44); // ugly
You could write the Magic class like this:
struct Magic {
Magic(Base &b) : b(b) {}
Base &b;
struct AA {
Base &b;
void operator*(int n) const {
return b.aa(n);
}
};
struct BB {
Base &b;
void operator*(int n) const {
return b.bb(n);
}
};
AA as_AA() { return AA{b}; }
BB as_BB() { return BB{b}; }
};
This avoids any inheritance by using composition instead. Also, there is no copy of the data object, since only references are being made to it.
Now you can use exactly the calling syntax that you want, and it has the right behavior:
Base data;
Magic obj(data);
obj.as_AA() * 33; // calls data.aa(33) -- prints 66
obj.as_BB() * 44; // calls data.bb(44) -- prints 176
Here's a demo.
One solution for using the same function name is to strongly type the argument:
struct AA {
int n;
};
struct BB {
int n;
};
void call(Base& base, AA arg) {
base.aa(arg.n);
}
void call(Base& base, BB arg) {
base.bb(arg.n);
}
...
Base data;
call(data, AA{33});
call(data, BB{44});
I took the liberty of getting rid of the operator overloading since this still accesses different implementations using the same name.
If you're trying to go further by having the same calling code with the selection being done in advance, you can use a higher-order function:
auto call_aa(Base& base) {
return [&](int n) { return base.aa(n); };
}
auto call_bb(Base& base) {
return [&](int n) { return base.bb(n); };
}
...
Base data;
auto aa = call_aa(data);
aa(33);
call_bb(data)(44);
I have a weird problem. I made an example explaining what is the problem. I have 4 classes, one that gets a pointer to a class which is inherent to 2 others. Here is what it looks like :
The inherences classes:
class classA{
public:
classA(){}
virtual std::string getType(){return "classA";}
classA& operator=(const classA& classa) {return *this;}
};
class classB: public classA {
int b;
public:
classB(int n){b=n;}
virtual std::string getType() { return "classB"; }
void setB(const int b){this->b=b;}
int getB() const{return this->b;}
};
class classC: public classA {
int c;
public:
classC(int n){c=n;}
virtual std::string getType() { return "classC"; }
void setC(const int c){this->c=c;}
int getC() const{return this->c;}
};
The only important thing is the getType() function.
Here is now the class that get a pointer to classA
class superClass{
classA* _classA;
int nb;
public:
superClass(){nb=0;}
void addElement(classA& e){
classA *newTab=new classA[++nb]; // create tab as the same size than the other +1
for(int i=0;i<nb-1;i++)
newTab[i]=_classA[i]; // add element from the old class to the new one
newTab[nb-1]=e; // add the element
//delete[] _classA;
_classA=newTab; // now copy it to the class
//delete[] newTab;
}
classA* getClass() {return _classA;}
int getNb() const{return this->nb;}
void displayElements(){
for(int i=0;i<getNb();i++)
std::cout << _classA[i].getType() << std::endl;
}
};
addElemment() is a function that malloc a classA element with one space more, it is filled with the ancien elements then it adds the new element and here it goes. Is works BUT the problem is here. I don't use classA element, only its children. I want to add classB elements and classC elements the the superClass and get the class type with getType(); Here is the main file
int main(int argc, char const *argv[])
{
classB *classb = new classB(9);
classC *classc = new classC(10);
superClass super;
super.addElement(*classb);
super.displayElements();
// Display "classA" instead of "classB"
super.addElement(*classc);
super.displayElements();
// Display "classA" and "classA" instead "classB" and "classC"
//std::cout << classb->getType() << std::endl; // return ClassA
//std::cout << classc->getType() << std::endl; // return ClassA
return 0;
}
I just want my program displaying the right class, the child one class. The problem comes with addElement() I think. I tried to use virtual std::string getType()=0; but it still doesn't work, it changes nothing.
I also tried using template but changes nothing and does not work
My question : I want my program displaying the child class instead of classA everytime.
You should change declaration member _classA in superClass to the following: classA** _classA;.
So it would be like this:
class superClass
{
classA** _classA;
int nb;
public:
superClass():_classA(0) // you also should initialize this to avoid crash while first delete[] of this _classA
{
nb = 0;
}
~superClass() // also you should add destructor to free memory
{
for (int i = 0; i < nb; i++)
{
delete _classA[i];
_classA[i] = nullptr;
}
delete[] _classA;
_classA[i] = nullptr;
}
void addElement(classA& e)
{
int oldSize = nb;
nb++; // increment the size separately for clarity
classA **newTab = new classA*[nb]; // create tab as the same size than the other +1
for (int i = 0; i < oldSize; i++)
newTab[i] = _classA[i]; // add element from the old class to the new one
classA* newElement = new classA(e); // use the copy-constructor
newTab[oldSize] = newElement; // add the element
delete[] _classA; // now you can free it
_classA = newTab; // now copy it to the class
}
classA** getClass()
{
return _classA;
}
int getNb() const
{
return this->nb;
}
void displayElements()
{
for (int i = 0; i < getNb(); i++)
std::cout << _classA[i]->getType() << std::endl;
}
};
newTab is an array of classA. Therefore, it cannot contain classB objects, only classA objects.
newTab[nb-1]=e;
Here, if e refers to a classB object, this assignment slices the classB part away from it, so it becomes a classA object and can fit in the array. This is known as object slicing.
The context: I wrote some tools for archiving data, in a similar way of archives from boost. Then, as example, I can write this kind of code :
class A
{
private:
double a;
public:
A() : a(3.14159)
{}
A(const A& a_) : a(a_.a) {}
virtual ~A()
{}
virtual A* clone() const = 0; // Then, A is virtual
virtual void save(O_Archive& oa) const //
{ //
oa << this->a; // INTERESTING
} // PART OF THE
virtual void load(I_archive& ia) // CLASS
{ //
ia >> this->a; //
} //
};
O_Archive& operator << (O_Archive& oa, const A& a)
{
a.save(oa);
return oa;
}
I_Archive& operator >> (I_Archive& ia, A& a)
{
a.load(ia);
return ia;
}
class B : public A
{
private:
double b;
public:
B() : A(), b(1.0) {}
B(const B& b_) : A(b_), b(b_.b) {}
virtual ~B() {}
virtual A* clone() const
{
return new B(*this);
}
void save(O_Archive& oa) const //
{ //
this->A::save(oa); //
oa << this->b; // INTERESTING
} // PART OF THE
void load(I_Archive& ia) // CLASS
{ //
this->A::load(ia); //
ia >> this->b; //
} //
};
// Consider classes 'C' and 'D' similar to 'B'
void example_save(O_Archive& oa)
{
A* p1 = new B;
A* p2 = new C;
D* p3 = new D;
oa << Archive::declare_derived<A,B,C,D>();
oa << p1 << p2; // Automatically detect the inheritance
oa << p3; // Store the instance as a usual pointer
}
void example_load(I_Archive& ia)
{
A* p1 = 0;
A* p2 = 0;
B* p3 = 0;
ia << Archive::declare_derived<A,B,C,D>();
ia >> p1 >> p2;
ia >> p3;
}
Where is the problem ? This works with several functions like the following load_pointer function in the class I_Archive in charge of checking if the pointer was allocated, if it was an instance with a derived type, or simply a usual pointer.
template <typename T>
void I_Archive::load_pointer(T*& p)
{
delete p;
bool allocated;
this->load_bool(allocated);
if(allocated)
{
bool inheriance;
this->load_bool(inheriance);
if(inheriance)
{
unsigned long int i;
this->load_unsigned_long_int(i);
p = boost::static_pointer_cast< const Archive::allocator<T> >(this->alloc[&typeid(T)][i])->allocate();
}
else
p = new T; // ERROR AT THIS LINE
*this >> *p;
}
else
p = 0;
}
My problem: Actually, my code doesn't compile with the following error on the line p = new T; :
error: cannot allocate an object of abstract type ‘A’.
I was first surprised, but I really well understand why I have this error : when the function load_pointer is called on p1, the instruction new T becomes new A which is forbidden, even if the instruction is never run if the type is abstract.
My question: I can't find a way to correctly use templates to avoid my error. Is there a possible workaround to do that or to say to the compiler "I know what I'm doing, you'll never have to instanciate an abstract type" ?
Important note: I can't work with C++11 for compatibility reason.
The trait you're looking for is std::is_abstract. As you mentioned, you cannot use C++11, but you can use its implementation from boost.
You can then use is_abstract together with std::enable_if (again, due to your restriction of not using C++11, you can just take the example implementation from here) to implement it similarly to this:
#include <iostream>
#include <type_traits>
struct A {
virtual void f() = 0;
};
struct B : A {
void f() override {}
};
template<typename T>
std::enable_if_t<std::is_abstract<T>::value, T*> allocate()
{
return nullptr;
}
template<typename T>
std::enable_if_t<!std::is_abstract<T>::value, T*> allocate()
{
return new T;
}
// Test
template<typename T>
T* test_alloc()
{
return allocate<T>();
}
int main()
{
std::cout << test_alloc<A>() << "\n"; // Outputs nullptr
std::cout << test_alloc<B>() << "\n"; // Outputs an address
}
LIVE
I have a type hierarchy similar to the code sample below, and I'm trying to instantiate them via the factory pattern (or, to be pedantic, rather the builder pattern, as my factory takes input from an XML document... but I digress).
However I try to do this, I'm running into problems which I suspect are due to either slicing, if I return by value, or to scoping, if I return by reference.
The below program, for instance, segfaults on the line a.doA() inside C::doStuff(). If I change the call to value_C_factory<C>() to ref_C_factory<C>() instead, I get a couple of warnings to the effect of "returning reference to temporary", but the program compiles, segfaults instead on b.doB() on the next line (without having printed anything from a.doA()...).
The backtrace from gdb looks like this - the second line is the one in my code referred to above
#0 0x00007ffff7dbddb0 in vtable for std::ctype<char> () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#1 0x00000000004010e9 in C::doStuff (this=0x7fffffffdd00) at syntax.cpp:57
#2 0x0000000000400cf2 in main () at syntax.cpp:95
What is causing these segfaults? Is it, as I suspect, slicing/scoping in the value/reference case? If not, what is it? And most importantly, what is a good way to build my instances from the input data?
Code sample
The code below should compile and give the above behavior with e.g. GCC 4.8, using
gcc -g -Wall -std=c++11 -o test test.cpp (that's what I do, anyway).
#include <iostream>
#include <typeinfo>
class IA {
public:
virtual void doA() const = 0;
virtual ~IA() { }
};
class A : public IA {
private:
std::string atask;
public:
explicit A(const std::string &task) : atask(task) {
std::cout << "Created A with task " << atask << std::endl;
}
void doA() const {
std::cout << "I did A! " << atask << std::endl;
}
};
class IB {
public:
virtual void doB() const = 0;
virtual ~IB() { }
};
class B : public IB {
private:
std::string btask;
public:
explicit B(const std::string &task) : btask(task) {
std::cout << "Created B with task " << btask << std::endl;
}
void doB() const {
std::cout << "I did B! " << btask << std::endl;
}
};
class IC {
public:
void doStuff() const;
virtual ~IC() { }
};
class C : public IC {
private:
const IA &a;
const IB &b;
public:
C(const IA &a, const IB &b) : a(a), b(b) { }
void doStuff() const {
a.doA(); // with value factory method, segfault here
b.doB(); // with reference factory, segfault here instead
}
};
template<typename TA>
TA value_A_factory() {
return TA("a value");
}
template<typename TB>
TB value_B_factory() {
return TB("b value");
}
template<typename TC>
TC value_C_factory() {
return TC(value_A_factory<A>(), value_B_factory<B>());
}
template<typename TA>
const TA &ref_A_factory() {
return TA("a ref");
}
template<typename TB>
const TB &ref_B_factory() {
return TB("b ref");
}
template<typename TC>
const TC &ref_C_factory() {
const TC &c(ref_A_factory<A>(), ref_B_factory<B>());
return c;
}
int main() {
C c = value_C_factory<C>();
std::cout << typeid(c).name() << std::endl;
c.doStuff();
}
You have two problems, both caused by undefined behavior.
The first is that you can't return a reference to a local variable. Once the function returns and the local variable goes out of scope and is destructed, what does the returned reference then reference?
The other problem is that you store references to temporary values. When you create your C class like TC(value_A_factory<A>(), value_B_factory<B>()) the values returned by the value_X_factory functions are temporary, and will be destroyed once the complete expression (TC(...)) is done.
In
template<typename TA>
const TA &ref_A_factory() {
return TA("a ref");
}
returning a reference to a local variable is undefined behavior.
In
TC(value_A_factory<A>(), ...)
the lifetime of the value returned by value_A_factory will be the end of the expression TC(...). After that your references in C are dangling.
If you really want to use interfaces and factories for polymorphic types, there is no real alternative to dynamic memory allocation and some kind of ownership scheme. The simplest would be for C to simply assume ownership of its members and take care of their deletion.
#include <memory>
#include <cassert>
struct IA {
virtual void doA() const = 0;
virtual ~IA() { };
};
struct A : IA {
void doA() const override {}
};
struct C {
/* C assumes ownership of a. a cannot be null. */
C(IA* a) : a{a} { assert(a && "C(IA* a): a was null"); };
private:
std::unique_ptr<IA> a;
};
C factory() {
return C{new A};
}
int main()
{
C c = factory();
return 0;
}