I didn't think it was possible, but if you have two instances of the same class, are you allowed to access one's private members from the other?
Is this why you can also do this in copy constructors? in fact, is the copy constructor the reason this is allowed? Doesn't this break encapsulation?
Yes, any code within a class can access private data in any instance of the class.
This breaks encapsulation if you think of the unit of encapsulation as the object. C++ doesn't think of it that way; it thinks of encapsulation in terms of the class.
Access restrictions are a property of the class, not of an instance.
That's why you can write your usual copy constructor:
class Foo
{
int a; // private!
public:
Foo (Foo const & rhs) : a(rhs.a) { } // rhs.a is accessible
};
This idea is also what fuels the "factory" idiom:
class Bar
{
Bar() { } // private?!
public:
static Bar * create() { return new Bar(); } // Bar::Bar() is accessible
};
Related
I have a class inheriting from another. I don't want users of this class to accidentally use base-class functions on the child object. The obvious answer is to make the inheritance protected or private.
However, I do want implicit casting from the child object to the base class. The default implementation of this cast is hidden in most contexts as it's given the protected/private status, and attempting to define a user conversion throws the warning that
"converting ‘B’ to a reference to a base class ‘A’ will never use a type conversion operator [-Wclass-conversion]"
Fair enough. With that avenue closed to me, I must turn here and ask: is there some way to reclassify the default type conversion into the public space so that implicit casting can live on?
As an example of what I'm trying to get working:
class A
{
public:
A()
{
}
A(A& otherA)
{
}
};
class B : protected A
{
public:
operator A& ()
{
return *this;
}
};
int main() {
B guy;
A otherguy(guy);
}
Sadly, I can't just declare the offending functions within the base class as protected: I want them available if the user explicitly casts to that base class. In my particular case, B contains no data and is merely a convenience/safety wrapper around A, so I don't need to worry about slicing or otherwise losing any information by allowing this cast. I just don't want users mistaking the backend API (which is exposed currently via public inheritance) for parts of the more user-friendly wrapper API.
I don't think you can do what you want in the way you've asked to do it.
I'd use encapsulation instead of inheritance:
class A {
public:
T func1(); // should be visible via B
void func2(); // should not be visible via B
};
class B { // note: not inheriting from A
A base; // B explicitly defines its "base class sub-object"
public:
// provide access to base class sub-object
operator A&() { return base; }
// provide access to func1
T func1() { return base.func1(); }
};
void use(A &a) { a.func2(); }
int main() {
B b;
b.func1(); // no problem
// b.func2(); // won't work;
use(b); // no problem. Uses our conversion operator
}
We are in the process of deprecating ACE libraries in our project which consists of around 120 binaries and in many of binaries we have used ACE_Singleton.Since after deprecating we will not have this class so we are thinking of writing our own generic singleton in our shared library that is common across all these binaries and one of the goals that we want to achieve is if somebody inherit from this class (using CRTP) say Logger and even when Logger constructor is public then also we cannot create two logger object.
To illustrate let's assume my singleton class name is GenericSingleton and my client class is logger then following code should throw error :
class Logger:public GenericSingleton<Logger>
{
public:
Logger()
{
}
};
int main()
{
Logger obj;// first instance no issue
Logger obj1; // second instance is problem as it is inherited from singleton
}
So can somebody suggest me how GenericSingleton should be designed so that while creating second object i should get compiletime error ?
In short is there a way that if my derived class doesn't have private constructor,destructor copy constructor etc. then it can be checked at compiletime using static_assert ?
There's no way for a constructor to know at compile time where or how many times it will be called; constructors are just functions, and functions don't know anything about their contexts. Consider that any static_asserts will be evaluated when the class is compiled, but this can (and almost certainly will!) happen in an entirely different translation unit from code that actually instantiates the class.
In any case, it seems unlikely that this would be helpful, because you must have some way to access singletons throughout your codebase.
Additionally, it's unclear why you want to permit your singletons to have public constructors. If you want to enforce singleton behavior at compile time for a completely arbitrary class just by adding an inheritance declaration, you're out of luck; arbitrary classes can be, well, arbitrarily constructed.
Since you're transitioning from the ACE singleton, I suggest you use a similar API; note that the ACE singleton documentation recommends making your singleton constructors private.
If, however, you just want some way to force your client to write a constructor that can't (easily) be called improperly, you can do something like this:
template <typename T>
class SingletonBase {
protected: class P { friend class SingletonBase<T>; P() = default; };
public:
SingletonBase(P) {}
static T& Instance() {
static T instance { P {} };
return instance;
}
};
(You will also need to delete the base class's copy and move constructors. Here is a working example use case. Note that declaring P's constructor =default does not prevent the singleton class from default-initializing instances of P. )
Now, because the base class constructor takes an argument of type P, the singleton class implementation must pass a P to its parent class constructor. But since the constructor for P is private, the singleton class won't be able to construct an instance of P except by copy or move construction, so its constructor must take an instance of P. But since P itself is protected, only the singleton class and the parent class can actually use it, so effectively the only possible call to the child's constructor must be in the Instance method.
Note that you do not need to explicitly declare and define the singleton-class's constructor, which would be ugly because of the need to use SingletonBase<Singleton>::P. You can simply expose the constructor with a using declaration:
using BASE = SingletonBase<Myclass>;
using BASE::SingletonBase;
You need to make sure that instances of Logger cannot be created outside the function that creates the sole instance of Logger.
Here's a simple implementation.
template <typename T> class GenericSingleton {
public:
static T& instance() {
static T instance_;
return instance_;
}
};
class Logger: public GenericSingleton<Logger>
{
// Make sure that the base class can create the sole instance of
// this class.
friend GenericSingleton<Logger>;
private:
// Makes sure that you cannot create objects of the class
// outside GenericSingleton<Logger>
~Logger() {}
public:
void foo() {}
};
int main()
{
// OK. Call foo() on the only instance of the class.
Logger::instance().foo();
// Not OK.
Logger obj1;
}
My advice would be to separate concerns. There is the concept of a service (such as a logger) and the service may or may not be a singleton. But this is an implementation detail, and therefore a separate concern. The consumer of the service ought to be agnostic of it.
Now, later in the lifecycle of the project, when you realise that singletons were a terrible idea, you can refactor the singleton without having to refactor any code that depends on it.
e.g.:
template<class Impl>
struct implements_singleton
{
using impl_type = Impl;
static impl_type& get_impl()
{
static impl_type _{};
return _;
}
};
struct logger_impl
{
void log_line(std::string const& s)
{
std::clog << s << std::endl;
}
};
struct logger
: private implements_singleton<logger_impl>
{
void log_line(std::string const& s) {
get_impl().log_line(s);
}
};
void do_something(logger& l)
{
l.log_line("c");
}
int main()
{
logger a;
logger b;
a.log_line("a");
b.log_line("b"); // behind the scenes this is the same logger
// but the user need not care
do_something(a);
}
How can I properly implement a copy constructor for my iterator, knowing that the pointer to the data object is private? Do I need to create an accessor for this pointer? Isn't this a bad thing?
Since you define a copy constructor for an iterator inside the implementation of the iterator itself, there is no need to make the hidden pointer accessible, with or without an accessor: the copy constructor will have access to it even if it is private, so there's nothing to worry about:
template <class T>
class MyIter {
T *private_ptr;
public:
MyIter(const MyIter<T> &other) : private_ptr(other.private_ptr) {}
... // More constructors and member functions
};
All member functions of a class have access to the data members of the class. This also applies to different objects of the same type.
class Foo()
{
private:
int bar;
public:
void foobar(Foo & different) { bar = different.bar; }
};
I am overloading operator= on a struct EqualTestBase, and operator= takes different parameters than are used to construct the struct.
struct EqualTestBase
{
EqualTestBase(int one) {}
EqualTestBase& operator=(std::string two)
{
//stuff
return *this;
}
};
It works fine on the base class. But a trival struct derived from it, EqualTestDerived, acts like it doesn't have the operator= member function.
struct EqualTestDerived : public EqualTestBase
{
EqualTestDerived(int one) : EqualTestBase(one) {}
};
void test()
{
EqualTestBase basetest(0);
basetest = "test"; //this is fine, compiles
EqualTestDerived derivedtest(0);
derivedtest = "test"; //this does not compile, says there is no constructor that takes type const char[5]
}
Do I have to redefine operator= on all derived structs, or is there a way to automatically pass down that functionality?
The derived class has an implicitly-declared copy-assignment operator, which hides the one declared in the base class. You can use using to bring it into scope:
struct EqualTestDerived : public EqualTestBase
{
EqualTestDerived(int one) : EqualTestBase(one) {}
using EqualTestBase::operator=;
};
operator= isn't inherited. If a class doesn't define operator= itself, the compiler will synthesize one for it (regardless of the fact that its base class does define an operator=).
If you want something that can be inherited (and can be virtual) you generally want to define it as a function with a different name. The generally accepted name for such a function is clone (though clone is normally more like a copy constructor, creating a new instance of an object, not just assigning to an existing one).
Why would anyone declare a constructor protected? I know that constructors are declared private for the purpose of not allowing their creation on stack.
When a class is (intended as) an abstract class, a protected constructor is exactly right. In that situation you don't want objects to be instantiated from the class but only use it to inherit from.
There are other uses cases, like when a certain set of construction parameters should be limited to derived classes.
Non-public constructors are useful when there are construction requirements that cannot be guaranteed solely by the constructor. For instance, if an initialization method needs to be called right after the constructor, or if the object needs to register itself with some container/manager object, this must be done outside the constructor. By limiting access to the constructor and providing only a factory method, you can ensure that any instance a user receives will fulfill all of its guarantees. This is also commonly used to implement a Singleton, which is really just another guarantee the class makes (that there will only be a single instance).
The reason for making the constructor protected, rather than private, is the same as for making any other method or field protected instead of private: so that it can be inherited by children. Perhaps you want a public, non-virtual factory method in the base class, which returns references to instances of the derived classes; the derived classes obviously want access to the parent constructors, but you still don't want to be creating them outside of your factory.
A protected constructor can be used to make a class effectively abstract when none of its methods are pure-virtual.
It is not quite abstract in the C++ sense since friend classes can still use it without overriding, but then you would have to declare these.
A protected constructor means that only derived members can construct instances of the class (and derived instances) using that constructor. This sounds a bit chicken-and-egg, but is sometimes useful when implementing class factories.
one use could be factory patterns
For factory methods with side-effects.
class mine {
private:
mine () {};
protected:
mine(int id) : m_id(id) {};
int m_id;
static int m_count;
public:
static mine* CreateOneOfMe() {
return mine(m_count++);
}
int GetId() { return m_id; }
};
This creates instances of the class and guarantees that each of them has a unique incrementing integer id. Note that if the constructor you want to use is not the default, you must hide the default too.
To let a subclass use a constructor that should not be accessible to an instantiator directly.
You could use it to limit the classes that could create it, for example:
class Level
{
private:
Level();
~Level();
friend class LevelManager;
};
The only class that can create an instance of it is the LevelManager class, so you will always know that the Level instance is created in the LevelManager.
One use of protected constructor is to implement the CRTP pattern, see the code below:
#include <iostream>
#include <assert.h>
template <class T>
class ComparableMixin {
public:
bool operator !=(ComparableMixin &other) {
return ~(*static_cast<T*>(this) == static_cast<T&>(other));
}
bool operator <(ComparableMixin &other) {
return ((*(this) != other) && (*static_cast<T*>(this) <= static_cast<T&>(other)));
}
bool operator >(ComparableMixin &other) {
return ~(*static_cast<T*>(this) <= static_cast<T&>(other));
}
bool operator >=(ComparableMixin &other) {
return ((*static_cast<T*>(this) == static_cast<T&>(other)) || (*(this) > other));
}
protected:
ComparableMixin() {}
};
class Integer: public ComparableMixin<Integer> {
public:
Integer(int i) {
this->i = i;
}
int i;
bool operator <=(Integer &other) {
return (this->i <= other.i);
}
bool operator ==(Integer &other) {
return (this->i == other.i);
}
};
int main() {
Integer i(0) ;
Integer j(1) ;
//ComparableMixin<Integer> c; //compilation error!
assert (i < j );
assert (i != j);
assert (j > i);
assert (j >= i);
return 0;
}