Inherit Without Virtual Destructor - c++

I have two classes that are used in a project. One class, Callback, is in charge of holding information from a callback. Another class, UserInfo, is the information that is exposed to the user. Basically, UserInfo was supposed to be a very thin wrapper that reads Callback data and gives it to the user, while also providing some extra stuff.
struct Callback {
int i;
float f;
};
struct UserInfo {
int i;
float f;
std::string thekicker;
void print();
UserInfo& operator=(const Callback&);
};
The problem is that adding members to Callback requires identical changes in UserInfo, as well as updating operator= and similarly dependent member functions. In order to keep them in sync automatically, I want to do this instead:
struct Callback {
int i;
float f;
};
struct UserInfo : Callback{
std::string thekicker;
void print();
UserInfo& operator=(const Callback&);
};
Now UserInfo is guaranteed to have all of the same data members as Callback. The kicker is, in fact, the data member thekicker. There are no virtual destructors declared in Callback, and I believe the other coders want it to stay that way (they feel strongly against the performance penalty for virtual destructors). However, thekicker will be leaked if a UserInfo type is destroyed through a Callback*. It should be noted that it is not intended for UserInfo to ever be used through a Callback* interface, hence why these classes were separate in the first place. On the other hand, having to alter three or more pieces of code in identical ways just to modify one structure feels inelegant and error-prone.
Question: Is there any way to allow UserInfo to inherit Callback publicly (users have to be able to access all of the same information) but disallow assigning a Callback reference to a UserInfo specifically because of the lack of virtual destructor? I suspect this is not possible since it is a fundamental purpose for inheritance in the first place. My second question, is there a way to keep these two classes in sync with each other via some other method? I wanted to make Callback a member of UserInfo instead of a parent class, but I want data members to be directly read with user.i instead of user.call.i.
I think I'm asking for the impossible, but I am constantly surprised at the witchcraft of stackoverflow answers, so I thought I'd ask just to see if there actually was a remedy for this.

You could always enforce the 'can't delete via base class pointer' constraint that you mentioned (to some extent) by making the destructor protected in the base class:
i.e.
// Not deletable unless a derived class or friend is calling the dtor.
struct Callback {
int i;
float f;
protected:
~Callback() {}
};
// can delete objects of this type:
struct SimpleCallback : public Callback {};
struct UserInfo : public Callback {
std::string thekicker;
// ...
};
As others have mentioned, you can delete the assignment operator. For pre-c++11, just make an unimplemented prototype of that function private:
private:
UserInfo& operator=(const Callback&);

struct UserInfo : Callback {
...
// assignment from Callback disallowed
UserInfo& operator=(const Callback&) = delete;
...
};
Note that the STL features a lot of inheritance without a virtual destructor. The documentation explicitly states that these classes are not designed to be used as base classes.
some examples are vector<>, set<>, map<> ....
Another approach is to consider private inheritance while providing an accessor method to reveal the Callback (in which case you may as well use encapsulation which is cleaner).

Yes, there's trickery you can use to keep the members in sync and update operator= automatically. It's ugly though, involving macros and an unusual way of using an include file.
CallBackMembers.h:
MEMBER(int, i)
MEMBER(float, f)
Elsewhere:
struct Callback {
#define MEMBER(TYPE,NAME) TYPE NAME;
#include "CallbackMembers.h"
#undef MEMBER
};
struct UserInfo {
#define MEMBER(TYPE,NAME) TYPE NAME;
#include "CallbackMembers.h"
#undef MEMBER
std::string thekicker;
void print(); // you can use the macro trick here too
UserInfo& operator=(const Callback& rhs)
{
#define MEMBER(TYPE,NAME) NAME = rhs.NAME;
#include "CallbackMembers.h"
#undef MEMBER
return *this;
}
};

There is no way to meet ALL the criteria you want.
Personally I think your idea to make it a member and then use user.call.i is the best and most clear option. Keep in mind that you write code that uses this just once, but you make up for it in maintainability (since your UserData never has to change) and readability (since it's 100% transparent to the end-use which attribute are part of the callback data and which are auxiliary).
The only other option that might make sense is to use private inheritance instead, and using the attribute or function into UserData. With this you still have to add one using when new data is added to callback, but you get your desired user.i syntax for clients.

Related

Data hiding worth for simple data containers

In my company, we generate code from XML. The code generator generates header files that contain Messages, and each message contains only data. NOTE we don't do any validation while setting or returning data; also, we don't have to take care of the state, i.e., data x and data in a message are independent; if x is changed, we don't need to change the state of y.
Current header file
class somemessage
{
private:
Field _field;
.......
public:
Field& getfield(){...}
const Field& getfield() const {...}
void setfield(const Field& field){....}
} ;
Do we still need data hiding here if it's only data? Do we require getter and setters in these headers, or can se make it simple as following.
struct somemessage
{
Field field;
};
We can make the message read-only when required using const as following.
void message_consumer(const somemessage& message)
{
message.field = somevalue; // compilation error
}
What are the disadvantages of this approach, and what are the advantages of using accessors and mutators?
If you have the following pattern:
class A {
public:
void SetFoo(const Foo& newFoo) {
f = newFoo;
}
const Foo& GetFoo() const {
return f;
}
protected:
private:
Foo f;
};
That is, you have a getter/setter pair and all they do is have a single return statement and a single assignment expression, then there's no need for the data member to be private and instead just make the data member public and remove the getter/setter pair.
class A {
public:
Foo f;
protected:
private:
};
If your getters/setters do anything else, or are in any way more complicated, then yes, having a getter/setter pair is fine.
In terms of using a struct versus a class, I go with struct if the type is strictly only data; no functions, no constructors. If for whatever reason the data type needs functions, then it should be declared as a class.
Writing a getter like this:
Field& getfield(){...}
is not encapsulation. A user can do this:
Field& decapsulated = x.getField();
and now they have a reference to the private member that they can use to do what they like. All checking and bookkeeping in the setter is futile, because the user does not need it to modify the private member:
decapsulated = some_other_field;
Proper encapsulation has advantages. Though plain old structs with only public members have their place as well. If however all you do is writing boilerplate that does not encapsulate the data, you can leave away the boilerplate. Eventually it is up to you to decide what to use. Encapsulation has lots of advantages, but it is not a must.
Getters returning non-const references can be useful as convenience methods. They can provide easy means for the user to access the class data. Compare for example to std::vector::operator[] or std::vector::at(). Though one should not confuse that with data encapsulation.

Passkey idiom with std::make_shared. xmemory cannot access private Key constructor

In my program I need a factory function that provides instances of separate class because I need control over the details of each instance and to be aware of how many instances are in existence at a time. In particular returning a std::shared_ptr is ideal, but this is initially impossible due to a known issue with the "make" fucntions of the std::pointer types as they would need to be friends with my Widget class as well, which isn't portable since it relies on the current implementation of those methods that may change.
To get around this, I want to employ the Passkey idiom, which was directly recommend for this situation as described at the bottom of this: https://abseil.io/tips/134. I also based my implementation off the lessons learned here: https://arne-mertz.de/2016/10/passkey-idiom/
This is a sample project that uses my same setup as my full project:
#include <iostream>
class Widget
{
public:
class Key
{
friend class Factory;
private:
Key() {};
Key(const Key&) = default;
};
int mTest;
explicit Widget(Key, int test) { mTest = test; }
int getTestVar() { return mTest; }
};
class Factory
{
public:
int mTestPass;
Factory(int input) { mTestPass = input; }
std::shared_ptr<Widget> factoryMake() { return std::make_shared<Widget>(Widget::Key{}, mTestPass); }
};
int main()
{
Factory testFactory(10);
std::shared_ptr<Widget> testWidget = testFactory.factoryMake();
std::cout << testWidget->getTestVar();
return 0;
}
However, I get
Error C2248 'Widget::Key::Key': cannot access private member declared in class 'Widget::Key' TestProject ...\include\xmemory 204
This has me completely lost, since the error coming from xmemory.cpp indicates that std::make_shared is sill trying to access a private constructor. As far as I'm aware, the construction of the Key instance occurs within the factoryMake() function, which belongs to Factory, and then that instance is passed into the std::make_shared function; therefore, std::make_shared should not need access to the Key constructor since an already constructed instance is being passed to it, which is the entire point of using this idiom in this context. The class itself is public so it should have no issues interacting with the type Key, only the constructor should be inaccessible.
In the end I can just skip using std::make_shared and instead use the shared_ptr(*T) constructor with a raw pointer, but this is slightly less efficient due to the extra allocation it requires, as noted in my first link. It isn't a big deal as I'm not making many widgets but I'd ultimately prefer to get the more ideal implementation working.
What am I missing here?
The problem is that the compiler needs to copy your Widget::Key when you call std::make_shared, and you have declared the copy constructor private. You can solve this in one of two ways:
Make the copy constructor of Widget::Key public.
Change the Widget constructor to take the Widget::Key by const reference:
explicit Widget(const Key&, ...

C++ : Access a sub-object's methods inside an object

I am starting to code bigger objects, having other objects inside them.
Sometimes, I need to be able to call methods of a sub-object from outside the class of the object containing it, from the main() function for example.
So far I was using getters and setters as I learned.
This would give something like the following code:
class Object {
public:
bool Object::SetSubMode(int mode);
int Object::GetSubMode();
private:
SubObject subObject;
};
class SubObject {
public:
bool SubObject::SetMode(int mode);
int SubObject::GetMode();
private:
int m_mode(0);
};
bool Object::SetSubMode(int mode) { return subObject.SetMode(mode); }
int Object::GetSubMode() { return subObject.GetMode(); }
bool SubObject::SetMode(int mode) { m_mode = mode; return true; }
int SubObject::GetMode() { return m_mode; }
This feels very sub-optimal, forces me to write (ugly) code for every method that needs to be accessible from outside. I would like to be able to do something as simple as Object->SubObject->Method(param);
I thought of a simple solution: putting the sub-object as public in my object.
This way I should be able to simply access its methods from outside.
The problem is that when I learned object oriented programming, I was told that putting anything in public besides methods was blasphemy and I do not want to start taking bad coding habits.
Another solution I came across during my research before posting here is to add a public pointer to the sub-object perhaps?
How can I access a sub-object's methods in a neat way?
Is it allowed / a good practice to put an object inside a class as public to access its methods? How to do without that otherwise?
Thank you very much for your help on this.
The problem with both a pointer and public member object is you've just removed the information hiding. Your code is now more brittle because it all "knows" that you've implemented object Car with 4 object Wheel members. Instead of calling a Car function that hides the details like this:
Car->SetRPM(200); // hiding
You want to directly start spinning the Wheels like this:
Car.wheel_1.SetRPM(200); // not hiding! and brittle!
Car.wheel_2.SetRPM(200);
And what if you change the internals of the class? The above might now be broken and need to be changed to:
Car.wheel[0].SetRPM(200); // not hiding!
Car.wheel[1].SetRPM(200);
Also, for your Car you can say SetRPM() and the class figures out whether it is front wheel drive, rear wheel drive, or all wheel drive. If you talk to the wheel members directly that implementation detail is no longer hidden.
Sometimes you do need direct access to a class's members, but one goal in creating the class was to encapsulate and hide implementation details from the caller.
Note that you can have Set and Get operations that update more than one bit of member data in the class, but ideally those operations make sense for the Car itself and not specific member objects.
I was told that putting anything in public besides methods was blasphemy
Blanket statements like this are dangerous; There are pros and cons to each style that you must take into consideration, but an outright ban on public members is a bad idea IMO.
The main problem with having public members is that it exposes implementation details that might be better hidden. For example, let's say you are writing some library:
struct A {
struct B {
void foo() {...}
};
B b;
};
A a;
a.b.foo();
Now a few years down you decide that you want to change the behavior of A depending on the context; maybe you want to make it run differently in a test environment, maybe you want to load from a different data source, etc.. Heck, maybe you just decide the name of the member b is not descriptive enough. But because b is public, you can't change the behavior of A without breaking client code.
struct A {
struct B {
void foo() {...}
};
struct C {
void foo() {...}
};
B b;
C c;
};
A a;
a.c.foo(); // Uh oh, everywhere that uses b needs to change!
Now if you were to let A wrap the implementation:
class A {
public:
foo() {
if (TESTING) {
b.foo();
} else {
c.foo();
}
private:
struct B {
void foo() {...}
};
struct C {
void foo() {...}
};
B b;
C c;
};
A a;
a.foo(); // I don't care how foo is implemented, it just works
(This is not a perfect example, but you get the idea.)
Of course, the disadvantage here is that it requires a lot of extra boilerplate, like you have already noticed. So basically, the question is "do you expect the implementation details to change in the future, and if so, will it cost more to add boilerplate now, or to refactor every call later?" And if you are writing a library used by external users, then "refactor every call" turns into "break all client code and force them to refactor", which will make a lot of people very upset.
Of course instead of writing forwarding functions for each function in SubObject, you could just add a getter for subObject:
const SubObject& getSubObject() { return subObject; }
// ...
object.getSubObject().setMode(0);
Which suffers from some of the same problems as above, although it is a bit easier to work around because the SubObject interface is not necessarily tied to the implementation.
All that said, I think there are certainly times where public members are the correct choice. For example, simple structs whose primary purpose is to act as the input for another function, or who just get a bundle of data from point A to point B. Sometimes all that boilerplate is really overkill.

Handle Body Idiom in C++

I have a class in my library which I want to expose to the users. I don't want to expose the whole class as I might want to make a binary incompatible changes later. I am confused with which of the following ways would be best.
Case 1:
struct Impl1;
struct Handle1
{
// The definition will not be inline and will be defined in a C file
// Showing here for simplicity
void interface()
{
static_cast<Impl1*>(this)->interface();
}
}
struct Impl1 : public Handle1
{
void interface(){ /* Do ***actual*** work */ }
private:
int _data; // And other private data
};
Case 2:
struct Impl2
struct Handle2
{
// Constructor/destructor to manage impl
void interface() // Will not be inline as above.
{
_impl->interface();
}
private:
Impl2* _impl;
}
struct Impl2
{
void interface(){ /* Do ***actual*** work */ }
private:
int _data; // And other private data
};
The Handle class is only for exposing functionality. They will be created and managed only inside the library. Inheritance is just for abstracting implementation details. There won't be multiple/different impl classes. In terms of performance, I think both will be identical. Is it? I am thinking of going with the Case 1 approach. Are there any issues that needs to be taken care of?
Your second approach looks very much like the compilation firewall idiom (sometimes known as the PIMPL idiom).
The only difference is that in the compilation firewall idiom, the implementation class is usually (but not always) defined as a member. Don't forget the constructor
(which allocates the Impl) and the destructor (which frees it). Along with the copy constructor and assignment operator.
The first approach also works, but it will require factory functions to create the objects. When I've used it, I've simply made all of the functions in the Handle pure virtual, and let the client code call them directly.
In this case, since client code actually has pointers to your object (in the compilation firewall idiom, the only pointers are in the Handle class itself), and the client will have to worry about memory management; if no cycles are possible, this is one case where shared_ptr makes a lot of sense. (The factory function can return a
shared_ptr, for example, and client code may never see a raw pointer.)

Conflict between providing (optional) functionality and encapsulation?

I need to provide a certain operation on the elements of my class Foo. This operation is specific and weird enough that I don't really want to make it a member function. On the other hand, it works on the internals of the class, which I don't want to expose.
Here is the class:
class Foo {
typedef std::map<int,double> VecElem;
std::vector<VecElem> vec_;
public:
void Insert(std::size_t index0, int index1, double d);
// ... other essential functions
};
void Foo::Insert(std::size_t index0, int index1, double d) {
vec_[index0][index1] = d;
}
The operation I need to support is to map the index1 of each element inserted so far to a new index, according to a given old-to-new index map:
void MapIndex1(const std::map<std::size_t,std::size_t>& old_to_new);
Given how Foo currently stores its elements this means a complete restructuring of the internal data, but this should not be exposed to the user. But also it shouldn't be a member function.
Is this a typical case of a friend non-member function? Are there any other possibilities? I don't really like the concept of a friend non-member function, because this weird function (which might be only temporarily necessary as a workaround for some problem) will still need to be mentioned inside the "official" class body (which is supposed to never change). But I guess I can't get around that?
What about a public nested class to do the work? Then it could have a MapIndex1 function that automatically gains access to the private members of its enclosing class. When you're done, just remove the nested class.
class Foo {
// ...
public:
void Insert(std::size_t index0, int index1, double d);
// ... other essential functions
class Remapper
{
public:
Remapper(Foo& foo) : foo_(foo) { }
void MapIndex1(const std::map<std::size_t,std::size_t>& old_to_new);
private:
Foo& foo_;
};
};
Foo myFoo;
Foo::Remapper remapper(myFoo);
remapper.MapIndex1(...);
An idea for dealing with this scenario is to add a function like:
void Ioctl(int func, void* params); to your class. This function can then be used as a gateways for all of these hackey temporary scenarios as they arise. They can then be safely removed when the requirement disappears without breaking compatibility (unless of course someone unofficially uses them).
True you do lose type safety but it does provide a nice swiss army knife approach for all such problems.
Internally you can define certain integer func values to call a function and cast the params value to whatever you need.