Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can a pointer alternatively point to a const empty class or a non-const class?

Tags:

c++

pointers

Presumably not. Here is my use case:

I have two classes A & B.

class A
{
    B *b_;
};        

class B
{
public:
    B(): b_string_("") {};

private:    
    std::string b_string_;
};

I want b_ to always point to a B object. I want b_ to point to an "empty" B object instead of nullptr so that I can always dereference *b_ in a defined manner to get an empty b_->b_string. So I thought I would create a global "null B object": const B null_b. But I can't (naturally) use this A ctor:

A(): b_(&null_b) {};

since b_ cannot point to a const variable. If not a "null B object", b_ needs to point to mutable B objects.

Making the global non-const solves the problem but I want the protection of const so I can guarantee the "null object" never changes.

FWIW, this involves a large project where b_ is pointing to an vector of B objects in another class. I could add an empty B object to that vector but that strikes me as kludgy.

Is there a method or pattern to solve my problem?

like image 621
Macbeth's Enigma Avatar asked Aug 01 '13 19:08

Macbeth's Enigma


3 Answers

Instead of holding a pointer to a B object, create a base class with virtual methods and store pointers to that. Derive both your B class and a Null_B class from it, but don't let methods on Null_B do modifications. Now even though your Null_B object won't be const, it doesn't matter anymore.

As an extra layer of protection you could make any attempt to modify the null_b object throw an exception so that you can detect and find your logic error.

like image 78
Mark Ransom Avatar answered Sep 28 '22 18:09

Mark Ransom


You can't have a "non-const" pointer point at a const object. And unfortunately, using const_cast to remove the const-ness of the object will mean that some code later can try to modify the object. (Note that it's undefined behaviour to cast away const unless the original object is non-const, so technically, the compiler is allowed to generated code that crash if this happens. Unfortunately, many cases, it WON'T crash when the object is something more complex than const char * or const int [] - allowing the code to happly continue after overwriting your object that you didn't want to be written).

However, since the B class has a b_string_ member that is private, no outside object could touch it, so you could ensure that any usage of b_string_ is done through a virtual function (or multiple virtual functions), then derive another class from B where the, and the virtual function(s) says "Sorry, you can't do that" when the code tries to modify b_string in the derived object.

like image 42
Mats Petersson Avatar answered Sep 28 '22 20:09

Mats Petersson


Well, maybe it's totally off the point, but... Could you use instance of B instead of pointer to B inside A? This would solve potential nullptr dereferencing.

EDIT well, if B is too big, then you can create a lightweight wrapper around it, and store instance of that wrapper inside A. The wrapper would provide you something meaningful if B is nullptr.

like image 44
Haspemulator Avatar answered Sep 28 '22 19:09

Haspemulator