C++ pointers and classes - c++

Trying to solve this question for the last 45 minutes, but couldn't figure out the what I'm suppose to do. Here's the question.
class C; //forward declaration
class Cpointer {
public:
};
class C { //do not modify
int i;
public:
C(int _i=0) : i(_i) {}
Cpointer operator& () { return Cpointer(this); }
void Do() { std::cout << "i=" << i << std::endl; }
};
int main() {
Cpointer p (new C(100));
p->Do();
}
Complete class Cpointer so that the code compiles. Make sure there are no memory leaks.
As I understand CPointer class takes a C class as a parameter for the constructor.
When I try the below code I'm getting a compiler error telling that
"use of undefined type C" inside the CPointer's Do function.
class Cpointer
{
C* mCptr;
public:
Cpointer(C* cptr) : mCptr(cptr){}
void Do()
{
//mCptr->Do();
}
};

I feel slightly uneasy posting solution but since you say it's not a homework... Here it is:
class Cpointer {
C* ptr;
public:
Cpointer(C* c) : ptr(c) { }
~Cpointer() { delete ptr; }
C* operator->() { return ptr; }
};
There are three points here:
Constructor to get the C* pointer and store it in the improvided pointer-like class.
Destructor to remove the object heap-allocated C when p gets out of scope of main function.
Overloaded -> operator so that p->Do(); will correctly invoke the C::Do method.
Basically, what you were asked to implement is a partial functionality of the standard auto_ptr class.

Given the way Cpointer is used in main(), it has to be implemented like this:
class Cpointer
{
private:
C* c:
public:
Cpointer(C* _c) : c(_c) {}
~Cpointer() { delete c; }
C* operator ->() { return c; }
};
The problem is that Cpointer is also used by C's overriden '&' operator, and this kind of implementation will not work for that usage. Memory corruption will occur, especially if the C instance is declared on the stack (which is when an overriden '&' operator is usually needed). To really make this work correctly, C would have to be modified, either to stop using Cpointer, or to contain a reference count that Cpointer manages. Either way violates the "do not modify" restriction on C.

so that it compiles, and doesn't leak? ok.
class Cpointer
{
public:
Cpointer(C* c)
{ delete c; }
void Do()
{ }
Cpointer* operator ->()
{ return this; }
};

class C; //forward declaration
class Cpointer {
public:
C* mptr;
Cpointer(C *cptr){
mptr = cptr;
}
~Cpointer(){
delete mptr;
}
C* operator->() const {
return mptr;
}
};

Related

Can a parent class which is reinterpreted as a child class use the child's functions in its functions?

I want to call the child's function from parent's function in reinterpreted class, like below.
Example
#include <iostream>
class A {
public:
void func1() {
// some code
func2();
// some code
}
protected:
virtual void func2() {
printf("class A\n");
}
};
class B : public A {
protected:
virtual void func2() {
printf("class B\n");
}
};
int main() {
A* ab = new A();
ab->func1(); // this print "class A"
B* bab = reinterpret_cast<B*>(ab);
bab->func1(); // this also print "class A"
// I want to print "class B" when I use bab->func1()
}
In this situation, Is there any way to print class B using the reinterpreted class bab without redefining func1?
For C++ polymorphism to kick in, you must create an instance of the derived class somewhere, but you can store a pointer to the base class. Using the base-class pointer will dispatch to the overridden functions of the derived class. So your definition of A and B is fine, your usage in the main function is not. reinterpret_cast is not intended for this.
#include <iostream>
#include <memory>
class A {
public:
void func1() {
// some code
func2();
// some code
}
protected:
virtual void func2() {
printf("class A\n");
}
};
class B : public A {
protected:
virtual void func2() {
printf("class B\n");
}
};
int main() {
{
// This works, but don't do this. Naked "new" is not modern C++ and dangerous.
A* ab = new B();
ab->func1();
delete ab;
}
{
// VARIANT 2: use smart pointers
std::unique_ptr<A> ab = std::make_unique<B>();
ab->func1();
}
{
// VARIANT 3: A non-smart pointer is okay, as long as it
// 1. references an existing allocated object
// 2. the pointer does not outlive the object it points to
B b;
A* ab = &b;
ab->func1();
}
{
// VARIANT 4: Like Variant 3, but with reference instead of pointer
B b;
A& ab = b;
ab.func1();
}
}
Output
class B
class B
class B
class B
https://godbolt.org/z/8e5E85nx5
EDIT: Try to avoid allocation with new. Any memory allocated in this fashion must be freed by you using delete and it is very easy to forget (I did when I first wrote this answer, kinda proving my point). Even if you do delete the memory at the end of your function, there is the possibility that your code never reaches this statement, e.g. if exceptions are thrown somewhere between new and delete.Here is some further reading:
Why is it a bad idea to use 'new'?
Why should C++ programmers minimize use of 'new'?

Converting pointer of class A to class B in function return, when B has constructor with `A*`

In C++, can we return a pointer of A from a function whose actual return value is a different struct B which indeed has the first object as the pointer of A?
Consider the following scenario.
struct B {
A* ptr;
// code...
B(A* _ptr)
{
// code...
}
};
B foo()
{
A* tmp;
// code...
return tmp;
}
B bar()
{
A* tmp;
// code...
return B(tmp);
}
Will the foo() method work correctly? Will it be able to call the constructor?
Or foo() will not be able to call the constructor and it works only in the case when B was defined in the following way,
struct B {
A* ptr;
// code...
B(A* _ptr) : ptr(_ptr)
{
// some code (doesn't changes `ptr`)
}
};
OR in the following way
struct B {
A* ptr; // NO more data elements other than `ptr`
B (A* _ptr) : ptr(_ptr) {
// some code (doesn't changes `ptr`)
}
};
If it works, is it because A* ptr in B comes as the first object?
I'd like to know what are the possibilities for this on different C++ versions (<11, 11, 14, 17) or if it also depends on the compiler I use.
I suppose, bar is the best way to write it.
Let's test it!
#include <iostream>
struct A;
struct B {
B(A* _ptr)
{
std::cout << "I've been called!" << std::endl;
}
};
B foo()
{
A* tmp;
return tmp;
}
int main()
{
foo();
return 0;
}
The output of such simple program is:
I've been called!
Meaning that constructor has been called.
It's possible, because B (A* _ptr) is a conversion constructor. This type of constructor allows automatic conversion to the class being constructed.
Just as #john mentioned, to disable this behaviour we use explicit specifier.
explicit B(A*) and foo() is no longer accepted.
Additionally, as you can see, in my version of B, there is no member A* ptr; - it isn't required.
Further to what Jorengarenar said. Sometimes you want to disable this behaviour. This is what the explicit keyword does
#include <iostream>
struct A;
struct B {
explicit B(A* _ptr)
{
std::cout << "I've been called!" << std::endl;
}
};
B foo()
{
A* tmp;
return tmp;
}
int main()
{
foo();
return 0;
}
This version no longer compiles. return tmp; is an error but return B(tmp); would compile and call the constructor.

Override pointer-to-member-function

I have these two classes:
class A {
public:
A() { m_ptr = NULL; }
void (*m_ptr)();
void a() { if (m_ptr) m_ptr(); }
};
class B : public A {
public:
B() { m_ptr = b; }
void b() {
std::cout << "B::b() is called" << std::endl;
}
};
And I want to use them like this:
B b;
b.a();
and get the following to be called B::b().
Of course this is not being compiled as B::b is not of type void(*)().
How can I make it work?
UPDATE. To whom who asks "why?" and "what for?".
The class A is a very basic class which has many successors in production code. The class B is 6-th successor and I want to extend A (the most convinient place) to call there one more method (from B) which can be present and may be not in another successors af A and B.
A virtual method with empty body can be employed for that but it is ugly and I want to avoid it. Abstract method even more so (because of existing derived successors code).
I don't want to use external function of type void (*)() to not loose access to internal data of all hierarchy.
You can't make it work as your classes are defined now.
Calling a non-static member function of another class requires an instance of that class. You either need to store a reference to the object that owns the member function when storing the function pointer, or pass a reference to the object when you make the call to A::a.
You also need to declare m_ptr with the type void (B::*)(), which is pointer to member of B that is a function taking no parameters and returning void.
Look at this example:
class A {
public:
A() { m_ptr = nullptr; }
void a(B& b) { if (m_ptr) (b.*m_ptr)(); } // Now takes reference to B object.
void (B::*m_ptr)(); // Pointer to member function of B.
};
class B : public A {
public:
B() { m_ptr = &B::b; } // Adress of qualified function.
void b() {
std::cout << "B::b() is called" << std::endl;
}
};
Now we can call B::b like this:
B b;
b.a(b); // Pass reference to b when calling.
Your use of inheritence in this way is confusing as it implies that the real problem you are trying to solve is to invoka a member of a derived class through the base class. This is usually accomplished using a simple virtual function like this:
class A {
public:
virtual ~A() {}
void a() const { b(); } // Call b.
private:
virtual void b() const {}
};
class B : public A {
public:
virtual void b() const override { // C++11 override specifier (optional).
std::cout << "B::b() is called" << std::endl;
}
};
And used like this:
B b;
b.a(); // B::b is called.
Well, probably not the purpose of this exercise, but you can simply declare static void b() if you want to make it work.
Another option is to declare friend void b(), but then the "B::b() is called" printout would be stating a wrong fact.
I would suggest using CRTP since you want to avoid virtual mechanism. Note, however, your code might require some design changes to accommodate this pattern. But it does provide type safety and has no run-time overhead. Hope it helps.
Code on ideone.com:
#include <iostream>
#include <type_traits>
namespace so {
class B;
template<typename T>
class A {
public:
template<typename U = T, typename = typename std::enable_if<std::is_same<U, B>::value>::type>
void foo_A() {
std::cout << "foo_A : ";
static_cast<U *>(this)->foo_B();
}
};
class B: public A<B> {
public:
void foo_B() {
std::cout << "foo_B" << std::endl;
}
};
class C: public A<C> {
public:
void foo_C() {
std::cout << "foo_C" << std::endl;
}
};
} // namespace so
int main() {
so::B b_;
so::C c_;
b_.foo_A();
b_.foo_B();
//c_.foo_A(); Compile error: A<C>::foo_A() does not exist!
c_.foo_C();
return (0);
}
Program output:
foo_A : foo_B
foo_B
foo_C

Inheritance and derived attribute disappearing in C++

I'm quite new to the concept of inheritance, and to C++ too, so my problem may be really stupid...
class A {
public :
A() {}
A(string name) {name_ = name}
private :
string name_;
}
class B : public A {
public :
B() {}
B(string name, int number) {
name_ = name;
number_ = number;
}
private :
string name;
int number;
}
class C {
public :
C() {}
void addClass(int id, A* a) {
map[id] = a;
}
private :
Hash_Map<int, A*> map;
}
void main() {
C* c = new C();
for (int i = 0; i < 10; i++) {
B* b = new B("randomName", 50);
c->addClass(i, b); //1st problem
delete b; //2nd problem
}
}
1st problem : shouldn't "map" in "c" keep the attribute "number" from the class "B"? I know I put A* in parameter, but if I had several class that derived from A, how should I do it?
2nd problem : All of my attributes in "map" seem to get random values when I delete "b". I'm guessing the problem is that I need to copy "b" into a new object, but how can I do it if I have "A*" as my addClass() parameter? My pointer b seems to be converted into its parent class
EDIT : had to change several things in my code that I forgot...
Bunch of problems:
1) No initializing members within a class declaration! (Your edit fixed this)
class B : public A {
public :
B() : name("A"), number(0) {} // initialize in constructor. that's what they are for!
private :
string name;
int number;
}
(Repeat that for A's declaration as well)
2)
You're storing a copy of the pointer to A (that was passed in as argument to addClass)in your map, not the actual object.
So, your map holds: 100 -> pointer to b
Then you delete whatever b points to. What would you think map[100] contains now?
A pointer to garbage! So, don't delete the pointer outside! Let C take care of it.
3) (My previous answer had a glaring error and someone voted it up. So, I'll keep the earlier part and point out my mistake)
Don't use pointers unless you need to. Save yourself some work. Go play the guitar or read some of Herb Sutter's articles!
void main() {
// don't use pointers and require that you delete them (unless you need to)
B b; // default constructor is called automatically. it is destroyed for you, by the compiler
// at the end of its scope (in this case, closing brace of main() )
C c;
c.addClass(100, b);
}
Let's fix C too. Can we get rid of those nasty pointers?
class C {
public :
C() {}
void addClass(const int id, const A a) { // use const, its a good habit!
map[id] = a;
}
private :
Hash_Map<int id, A a> map;
}
Now, what's wrong with this? Not just extra copies; when you pass b as argument to addClass by value, the compiler is gonna copy the A portion of b! So, we lostb`'s data (and overrides)!
So, we absolutely have to use pointers (references are dangerous, since they're deleted at scope exit).
What's important is that you make C owns the deletion.
So your code would now look like:
class C {
public :
C() {}
~C() {
for(pair<int, A*>& p : map) // C++11 syntax, yay!
delete p.second; // here's where you clean up. not in main.
}
void addClass(const int id, const A* a) {
map[id] = a;
}
private :
Hash_Map<int, A*> map;
}
void main() {
B* b = new B(); // back to square 1!
C c;
c.addClass(100, &b);
} // no memory leaks
But I hate taking care of deletion you say.. Fear not, we have shared_ptr!
#include <memory>
using namespace std;
typedef shared_ptr<A> Aptr;
class C {
public :
C() {}
~C() {
cout << "Drinking a beer coz i use shared_ptr";
}
void addClass(const int id, Aptr& a) {
map[id] = a;
}
private :
Hash_Map<int, Aptr> map;
}
void main() {
Aptr b(new B());
C c;
c.addClass(100, b);
} // still no memory leaks
Hope that helps.

A strange access violation error

I have wrote a program that use inheritance, everything is OK but an error that I think shouldn't not be here naturally.
here is my program:
class A
{
protected:
int x;
public:
A(){};
~A(){};
A* operator=(const A* other)
{
this->x = other->x;
return this;
}
};
class B : public A
{
public:
B() : A(){};
~B(){};
};
class C
{
protected:
A *a;
public:
C(const A* other){ *(this->a) = other; };
};
int main()
{
B *b = new B();
C *c = new C(b);
return 0;
}
It produces an execution time error in the statement 'this->x = other->x;'.
What about this?
*(this->a) is undefined behavior, because this->a wasn't initialized - it's just a dangling pointer.
You can use a = new A; *a = other (the this-> in this case is redundant), but this isn't the proper C++ way - you should use RAII (look it up) - you wouldn't need destructors, assignment operators or copy constructors if you did.
Also, operator = typically returns *this by reference.
I like Luchian's answer but there is still some places to enhanced in your code, you may still encounter some undefined behavior in your code before you fix other potential bugs.
class A
{
protected:
int x;
public:
A():x(0){} // should always initialize x in constructor
virtual ~A()=0 {} // as A is a base case, ~A must be virtual
A& operator=(const A& other) // a reference will be more practical better?
{
this->x = other.x;
return *this;
}
};
If you don't want to make B object as well which means B is serviced as a base class, you should make its destructor virtual as well, even make it pure virtual.
class B : public A
{
public:
B() : A(){}
virtual ~B(){} =0
{ }
};
*(this->a) = other; is answered by Luchian already. In your code, if you want to keep a copy of pointer which points to A, you can simply initialize a_ptr in member initialize list
see below demo code:
class C
{
protected:
A *a_ptr;
public:
C(A* other):a_ptr(other){ }
};
Finally come to your main function, if b,c are only used in main function, when program finishes, system will claim dynamic allocated memory back, but if you use a,b in a loop, you need to delete them manually.