The following test code demonstrates an issue that I am having in a much larger application. In the application I have a service that "provides" several servers that are all derived from one base class. I then use createInstance to get "access" to a specific server based on a server type ('n' used below). dynamic_cast is then used to cast as the appropriate server. This all works fine.
The problem is when I try to use the deleteInstance to go back to the service and delete it, cleaning up any internal server related data. I cannot seem to find a good passing mechanism or if it is even valid way of achieving what I am doing.
#include <iostream>
#include <string>
class MM
{
public:
virtual ~MM() {}
virtual void start() = 0;
};
class M1 : public MM
{
public:
void start()
{
std::cout << "M1 start" << std::endl;
}
};
class M2 : public MM
{
public:
void start()
{
std::cout << "M2 start" << std::endl;
}
void start( const std::string strName )
{
std::cout << "M2 start - " << strName << std::endl;
}
};
MM * createInstance( int n )
{
if( 2 == n )
{
return new M2;
}
else
{
return new M1;
}
}
void deleteInstance( MM * & pInstance )
{
delete pInstance;
pInstance = NULL;
}
void deleteInstance2( MM ** ppInstance )
{
delete *ppInstance;
*ppInstance = NULL;
}
int main( int argc, char *argv[] )
{
M1 *pM1 = dynamic_cast<M1 *>( createInstance( 1 ) );
M2 *pM2 = dynamic_cast<M2 *>( createInstance( 2 ) );
pM1->start();
pM2->start();
pM2->start( "test" );
deleteInstance( pM1 );
deleteInstance( pM2 );
//deleteInstance2( &pM1 );
//deleteInstance2( &pM2 );
return 0;
}
To complete the info, the error that I am receiving for deleteInstance implementation:
68:25: error: invalid initialization of reference of type ‘MM*&’ from expression of type ‘M1*’
46:6: error: in passing argument 1 of ‘void deleteInstance(MM*&)’
69:25: error: invalid initialization of reference of type ‘MM*&’ from expression of type ‘M2*’
46:6: error: in passing argument 1 of ‘void deleteInstance(MM*&)’
and for deleteInstance2:
70:27: error: invalid conversion from ‘M1**’ to ‘MM**’
70:27: error: initializing argument 1 of ‘void deleteInstance2(MM**)’
71:27: error: invalid conversion from ‘M2**’ to ‘MM**’
71:27: error: initializing argument 1 of ‘void deleteInstance2(MM**)’
The problem is that binding a pointer to the derived type with a reference to a pointer to the base type would break the type system. Consider this motivating example:
void resetPtr( base*& b ) {
static base instance;
b = &instance;
}
int main() {
derived *d;
resetPtr( d ); // Now d points to a base, not a derived object!!!!
}
While you can work around this as some other answer points out (for example through the use of templates that will infer the appropriate type and so on), I would recommend that you redesign and pass the pointer by value.
Why is it a bad idea to reset the pointer to NULL after deletion?
The problem with reseting the pointer to NULL is that it does not really solve any problem, and adds problems of its own.
It does not solve the problem of knowing whether pointers are valid in your application, as in the general case you can have more than one pointer to a given object, and because you only delete one of them, only one of the pointers will be reset to NULL, and you are left (at least in most cases) with the same situation you had in the beginning.
It can help hide bugs in the logic of your application: after you reset the pointer to NULL, any potential issue in your application by which you delete the pointer twice will be hidden, as it is safe to delete a NULL pointer. While you might think that this is a good idea --after all, it avoids crashing your application-- in the long term it is a bad idea, since the core issue is still there: the design fails to provide proper ownership semantics.
The problem has nothing to do with base class vs. derived class pointers; the problem is simply that you've declared your method to accept a pointer to pointer to MM as an argument, and you're passing just a pointer to MM.
You could pass a pointer to MM by reference -- i.e.,
void deleteInstance( T* &pInstance ) ...
I'm not sure I like what you're trying to do, but I can't put my finger on why - I think the idea is fine. .. but heres a way you could implement it .
template<typename T>
void deleteInstance( T * & pInstance )
{
// This conversion is here so you get a nice error if
// you try to use it on a type that isn't derived from MM.
MM* tmp = pInstance;
delete tmp;
pInstance = NULL;
}
The reason why deleteInstance is not working is that you are taking a non-const reference to a temporary created by the conversion of M1* or M2* to MM*.
The reason why deleteInstance2 is not working is that Derived** is not convertible to Base**. This faq explains it very well.
Related
I want to get references to the MyObjectClass instance passed to "somePrivateMethod" called by myMock.
Now I use the following snippet but I'm sure there is a better way.
namespace {
MyObjectClass *myObjectPtr;
ACTION( getIt )
{
myObjectPtr = &arg0;
}
}
...
...
EXPECT_CALL( *myMock, somePrivateMethod( testing::_ ) ).WillOnce( testing::WithArg< 0 >( getIt( ) ) );
My problem is clearly stated I need to get the reference to that argument. The reason for what I want it has no matter here. I only need to know how to set a pointer to the argument of the somePrivateMethod.
One of the way to do this is write public get method in declaration of class A
public:
const int * get_b { return &b; }
But since you want to check the value of this variable you don't need a pointer and can return value of variable in get function
public:
int get_b { return b; }
I'm trying to do something that seems like it should be fairly common but I've been unable to find anyone discussing it. this post on stackoverflow is similar to what I'm trying to do, but not quite the same.
I have an abstract base class:
#ifndef _ABASECLASS_H_
#define _ABASECLASS_H_
using namespace std;
#include <iostream>
#define CALL_MBR_FUNC(object, ptr_to_mem_func) ((object).*(ptr_to_mem_func))
class aBaseClass
{
public:
typedef void (aBaseClass::*aBaseClass_mem_func)();
int A;
int B;
aBaseClass();
aBaseClass(int a, int b);
virtual void function1(aBaseClass_mem_func infunc) = 0;
virtual void function2() = 0;
};
#endif /* _ACLASS_H_ */
and I have a derived class:
#ifndef _ASUBCLASS_H_
#define _ASUBCLASS_H_
using namespace std;
#include <iostream>
#include "aBaseClass.h"
/* A simple class containing two ints and some functions to demonstrate passing via various methods. It is a subclass of aClass*/
class aSubClass: public aBaseClass
{
public:
aSubClass();
aSubClass(int a, int b);
void function1(aBaseClass_mem_func infunc);
void function2(void);
};
#endif /* _ASUBCLASS_H_ */
where function1 and function2 are:
void aSubClass::function1(aBaseClass_mem_func infunc)
{
CALL_MBR_FUNC(*this, infunc)();
}
void aSubClass::function2(void)
{
A = 42;
B = 66;
}
Finally, in the main() I try to call function1 targeted on an object of type aSubClass, passing a pointer to function2 in aSubClass:
int main (int argc, const char * argv[])
{
aSubClass eh(2,5);
// This doesn't work
aBaseClass_mem_func trythis = &aSubClass::function2;
// This also doesn't work
eh.function1(&aSubClass::function2);
return(0);
}
OK, we can automatically cast a pointer-to-derived type to a pointer-to-base type. I have now read that we can't pass a pointer-to-derived-member-function to a pointer-to-base-member-function. I think I understand why (the derived member function might make use of things that exist in the derived class but don't exist in the base class).
But I'm trying to build a library of two categories of classes (derived from two base classes). Call them baseclass1 and baseclass2. One of the member functions in any derived class from baseclass1 needs to be able to be handed a particular member function from any derived class from baseclass2. Is there some trick I can use to carry out the necessary cast? Do I have to use the explicit keyword and define the cast somehow?
You could shorten this example a lot:
struct B {
virtual void foo() = 0;
};
struct D : B {
void foo() override { }
};
int main() {
void (B::*ptr)() = &D::foo; // error: cannot initialize a variable of
// type 'void (B::*)()' with an rvalue of type
// 'void (D::*)()': different classes ('B' vs 'D')
}
The error message, at least on clang, is pretty clear. gcc just says cannot initialize. The issue is just that you cannot implicitly convert a pointer-to-derived-member to a pointer-to-base-member. But you can do it explicitly with static_cast:
void (B::*ptr)() =
static_cast<void (B::*)()>(&D::foo); // ok!
Side-note: please remove the CALL_MBR_FUNC macro from your code and never write such a thing ever again.
Why it doesn't work:
One way you can think of a member function is this:
struct Foo {
void go () { }
} ;
Could also be expressed as:
void go ( Foo* this ) { }
So, this:
typedef void(Foo::*MemberFunctionPtr)() ;
Is kind of like this:
typedef void(*MemberFunctionPtrForFoo)(Foo*) ;
However, if you have a subclass like this:
struct Bar : public Foo {
void go2 () { }
} ;
That function is also kind of like this:
void go2 ( Bar* this ) { }
So when you take the address of Bar::go2, you're getting basically a pointer to a function that looks like void go2 ( Bar* this ). Why is this a problem?
Well let's look at what this means...
If you had this function:
void function ( Foo * this ) ;
And you were to do this:
Bar * bar = new Bar () ;
function ( bar ) ;
This would work (as it should). C++ kindly made it possible for you then to be able to do things like this:
void(*functionPtr)(Bar*) = &Foo::go ;
However, lets say you instead had this function:
void function ( Bar * this ) ;
And you did this:
Foo * foo = new Foo() ;
function ( foo ) ;
This wouldn't work because foo isn't [necessarily] a Bar. You could static_cast that, which is your way of telling the compiler "no, really, I'm pretty sure I know what I'm doing" (as opposed to reinterpret_cast, which is your way of telling the compiler "you're stupid; I know what I'm doing.")
Therefore, it also won't let you cast the member functions.
Another answer said that static_cast can convert the member functions, but that's only because static_cast is allowed to do the reverse of implicit cast (except for cv-qualification). You can do it, but it has the same caveats.
Disclaimer: this is a fairly simplified version of the spec, but it gets the point across.
A better solution in most cases:
On to a [potentially] better solution [unless absolute performance is key]: boost::function (or, as of C++11 std::function). This is a "functor".
Your member function could instead be written:
class Foo {
void function ( boost::function<void()> function ) { }
} ;
The functor object can be constructed with anything that can be called with the specified prototype (in this case, something taking no arguments and returning void). You can pass the address of a C-function for instance.
Another thing you can do is "bind" functions (which basically grabs arguments and makes a function). There's boost::bind for this.
For example you could do this:
Foo foo ;
Bar bar ;
foo.function ( boost::bind(&Bar::go2,&bar) ) ;
The boost bind takes some function as the first argument. If the function is a member function, the next argument must either be an instance of a class that the specified method can be called on (in which case it's copied) or a pointer to a class the specified method can be called on (in which case it's referenced). This example would actually cause the foo instance to call the bar instance (instead of itself), but you could pass &foo instead.
You can even be more creative:
class Foo {
void function ( boost::function<void(int)> function ) {
function ( 1 ) ;
}
void go2 ( int a , int b ) {
cout << a << " " << b << endl ;
}
} ;
Foo foo ;
foo.function ( boost::bind(&Foo::go2,&foo,_1,2) ) ;
That bind grabs:
The member-function-pointer for Foo::go2
A reference (or, 'pointer') to that instance of foo
A placeholder for "the first argument of the resultant function," which'll become the first argument in the call to go2
The number 2, which'll become the second argument in the call to go2
This is what'll be printed to the console:
1 2
This is an extraordinarily powerful tool and will lead you into the fantastic world of functional programming while making your life easier along the way. (It'll also make people like #CortAmmon hate you.)
I have a thread-class Buffer (own made class), and many derived classes such as BufferTypeA, BufferTypeB...
Since I have to synchronize them in a certain order, I'm giving any of them an integer which represents the order to run certain task. I also have to know inside each thread Buffer which one is next to run the task, so I'm passing every BufferType a reference to an integer which all of them must share and I didn't want to make it Global.
I got lost at any point and I don't see where.
First I create all the BufferTypes from a class where I also define that shared integer as:
int currentThreadOrder;
And when creating the BufferTypes:
int position = 0;
if (NULL == bufferA) {
bufferA = new BufferTypeA(¤tThreadOrder, ++position,
waitCondition);
}
if (NULL == bufferB) {
bufferB = new BufferPos(¤tThreadOrder, ++position,
waitCondition);
}
if (NULL == bufferC) {
bufferC = new BufferRtk(¤tThreadOrder, ++position,
waitCondition);
}
Then, in BufferTypeA header:
class BufferTypeA: public Buffer {
public:
BufferTypeA(int currentThreadOrder,
int threadConnectionOrder = 0,
QWaitCondition *waitCondition = NULL);
//..
}
And in cpp file:
BufferTypeA::BufferTypeA(int currentThreadOrder, int threadConnectionOrder, QWaitCondition *waitCondition):
Buffer(currentThreadOrder, threadConnectionOrder, waitCondition) { }
Now I'll show Buffer header:
class Buffer: public QThread {
public:
Buffer(int ¤tThreadOrder,
int threadConnectionOrder = 0,
QWaitCondition *waitCondition = NULL);
//...
protected:
QWaitCondition *waitCondition;
int threadConnectionOrder;
int ¤tThreadOrder; // Shared address
}
And finally the cpp:
Buffer::Buffer(int ¤tThreadOrder, int threadConnectionOrder, QWaitCondition *waitCondition) {
this->threadConnectionOrder = threadConnectionOrder;
this->waitCondition = waitCondition;
this->currentThreadOrder = currentThreadOrder;
}
And the error I'm getting is error: uninitialized reference member Buffer::currentThreadOrder.
I'm embarrased to ask, because it's going to be a simple problem with pointers and addresses, but I can't see where the problem is, so please help.
When you create a class with a data-member that is a reference, the reference needs to be assigned a value in the constructor initializer list.
References have to be given a value when they are created, they are not pointers. They have to start with a value and that value cannot be changed (while the contents that is pointed to by that value can be changed).
Essentially you can think of a reference as an alias for an existing variable. You can't give a friend a nickname if you don't have a friend :)
RESPONSE TO COMMENT:
You don't "share a reference" between objects. Each object will have its own reference to the same variable. When you "pass by reference" you are telling the compiler that you want the variable in your function to actually be the variable in your outer scope, rather than creating a new variable by value. This means that you only have one variable at one memory location. The reference is just memory in some other place that forwards you to that same memory location.
Think of this as call forwarding... I can have 15 phone numbers in 15 different countries. I can set them all up to forward calls to my cell in the US. So, people are calling me no matter which number they call.
Each of your classes just has another reference to forward the "phone calls" or variable reads/writes to that same memory location. So, you're not sharing a reference between classes, you're making sure that each class HAS a reference to the same underlying memory location.
Back to the metaphore, each class won't have the same phone, but each class' phone will forward to the same number (variable) none-the-less which lets them all set/get the same value in the end.
RESPONSE II:
Here's a simple example to get your head going, it's pretty easy to apply to your classes. I didn't compile it but it should work minus a typo or two possibly.
class A
{
public:
A(int& shared) : m_shared(shared)
{
//No actions needed, initializer list initializes
//reference above. We'll just increment the variable
//so you can see it's shared in main.
m_shared += 7;
}
void DoSomethingWithIt()
{
//Will always reflect value in main no matter which object
//we are talking about.
std::cout << m_shared << std::endl;
}
private:
//Reference variable, must be initialized in
//initializer list of constructor or you'll get the same
//compiler error again.
int& m_shared;
};
int main()
{
int my_shared_integer = 0;
//Create two A instances that share my_shared_integer.
//Both A's will initialize their internal reference to
//my_shared_integer as they will take it into their
//constructors "by reference" (see & in constructor
//signature) and save it in their initializer list.
A myFirstA(my_shared_integer);
A mySecondA(my_shared_integer);
//Prints 14 as both A's incremented it by 7 in constructors.
std::cout << my_shared_integer << std::endl;
}
you pass a pointer int* as 1st argument to BufferTypeA, which expects and int, while you said in your question you meant to use a int&. To do this, the ctor of BufferTypeA should take a int& and initialise it in an initialisation list (i.e. not within the { } part of the ctor) like
class BufferType {
int &Ref;
public:
BufferTypeA(int& ref) : Ref(ref) { /* ... */ }
};
and in your construction of BufferA you must not pass an address, but the reference, i.e.
int counter;
Buffer = new BufferType(counter);
You want code like this:
Buffer::Buffer(
int ¤tThreadOrder0,
const int threadConnectionOrder0,
QWaitCondition *const waitCondition0
) :
threadConnectionOrder(threadConnectionOrder0),
waitCondition(waitCondition0),
currentThreadOrder(currentThreadOrder0)
{}
The reason is related to the reason you cannot write
const double pi;
pi = 3.14;
but can write
const double pi = 3.14;
A reference is typically implemented as a constant pointer, to which one cannot assign an address after one has initialized the pointer. Your version of the code assigns, as in the first pi example. My version of the code initializes, as in the second pi example.
Suppose I have a class:
class test {
public:
void print();
private:
int x;
};
void test::print()
{
cout<< this->x;
}
and I have these variable definitions:
test object1;
test object2;
When I call object1.print() this happens to store address of object1 and so I get x from object1 printed and when I call object2.print() this happens to store address of object2 and I get x from object2 printed. How does it happen?
Each non-static member function has an implicit hidden "current object" parameter that is exposed to you as this pointer.
So you can think that for
test::print();
there's some
test_print( test* this );
global function and so when you write
objectX.print();
in your code the compiler inserts a call to
test_print(&objectX);
and this way the member function knows the address of "the current" object.
You can think of the this pointer being an implicit argument to the functions. Imagine a little class like
class C {
public:
C( int x ) : m_x( x ) { }
void increment( int value ) {
m_x += value; // same as 'this->m_x += value'
}
int multiply( int times ) const {
return m_x * times; // same as 'return this->m_x * times;'
}
private:
int m_x;
};
which allows you to write code like
C two( 2 );
two.increment( 2 );
int result = two.multiply( 3 );
Now, what's actually happening is that the member functions increment and multiply are called with an extra pointer argument, pointing to the object on which the function is invoked. This pointer is known as this inside the method. The type of the this pointer is different, depending on whether the method is const (as multiply is) or not (as is the case with increment).
You can do something like it yourself as well, consider:
class C {
public:
C( int x ) : m_x( x ) { }
void increment( C * const that, int value ) {
that->m_x += value;
}
int multiply( C const * const that, int times ) const {
return that->m_x * times;
}
private:
int m_x;
};
you could write code like
C two( 2 );
two.increment( &two, 2 );
int result = two.multiply( &two, 3 );
Notice that the type of the this pointer is C const * const for the multiply function, so both the pointer itself is const but also the object being pointed to! This is why you cannot change member variables inside a const method - the this pointer has a type which forbids it. This could be resolved using the mutable keyword (I don't want to get side-tracked too far, so I'll rather not explain how that works) but even using a const_cast:
int C::multiply( int times ) const {
C * const that = const_cast<C * const>( this );
that->m_x = 0; // evil! Can modify member variable because const'ness was casted away
// ..
}
I'm mentioning this since it demonstrates that this isn't as special a pointer as it may seem, and this particular hack is often a better solution than making a member variable mutable since this hack is local to one function whereas mutable makes the variable mutable for all const methods of the class.
The way to think about it is that this is simply a pointer to the memory for whichever object you're currently working with. So if you do obj1.print(), then this = &obj1;. If you do obj2.print(), then this = &obj2;.
this has different values for different objects
Each instance of class test gets it's own copy of member variable x. Since x is unique for each instance, the value can be anything you want it to be.
The variable this, refers to the instance to which it is associated. You don't have to use the variable 'this'. You could just write:
void test::print()
{
cout << x;
}
Using C++ I built a Class that has many setter functions, as well as various functions that may be called in a row during runtime.
So I end up with code that looks like:
A* a = new A();
a->setA();
a->setB();
a->setC();
...
a->doA();
a->doB();
Not, that this is bad, but I don't like typing "a->" over and over again.
So I rewrote my class definitions to look like:
class A{
public:
A();
virtual ~A();
A* setA();
A* setB();
A* setC();
A* doA();
A* doB();
// other functions
private:
// vars
};
So then I could init my class like: (method 1)
A* a = new A();
a->setA()->setB()->setC();
...
a->doA()->doB();
(which I prefer as it is easier to write)
To give a more precise implementation of this you can see my SDL Sprite C++ Class I wrote at http://ken-soft.com/?p=234
Everything seems to work just fine. However, I would be interested in any feedback to this approach.
I have noticed One problem. If i init My class like: (method 2)
A a = A();
a.setA()->setB()->setC();
...
a.doA()->doB();
Then I have various memory issues and sometimes things don't work as they should (You can see this by changing how i init all Sprite objects in main.cpp of my Sprite Demo).
Is that normal? Or should the behavior be the same?
Edit the setters are primarily to make my life easier in initialization. My main question is way method 1 and method 2 behave different for me?
Edit: Here's an example getter and setter:
Sprite* Sprite::setSpeed(int i) {
speed = i;
return this;
}
int Sprite::getSpeed() {
return speed;
}
One note unrelated to your question, the statement A a = A(); probably isn't doing what you expect. In C++, objects aren't reference types that default to null, so this statement is almost never correct. You probably want just A a;
A a creates a new instance of A, but the = A() part invokes A's copy constructor with a temporary default constructed A. If you had done just A a; it would have just created a new instance of A using the default constructor.
If you don't explicitly implement your own copy constructor for a class, the compiler will create one for you. The compiler created copy constructor will just make a carbon copy of the other object's data; this means that if you have any pointers, it won't copy the data pointed to.
So, essentially, that line is creating a new instance of A, then constructing another temporary instance of A with the default constructor, then copying the temporary A to the new A, then destructing the temporary A. If the temporary A is acquiring resources in it's constructor and de-allocating them in it's destructor, you could run into issues where your object is trying to use data that has already been deallocated, which is undefined behavior.
Take this code for example:
struct A {
A() {
myData = new int;
std::cout << "Allocated int at " << myData << std::endl;
}
~A() {
delete myData;
std::cout << "Deallocated int at " << myData << std::endl;
}
int* myData;
};
A a = A();
cout << "a.myData points to " << a.myData << std::endl;
The output will look something like:
Allocated int at 0x9FB7128
Deallocated int at 0x9FB7128
a.myData points to 0x9FB7128
As you can see, a.myData is pointing to an address that has already been deallocated. If you attempt to use the data it points to, you could be accessing completely invalid data, or even the data of some other object that took it's place in memory. And then once your a goes out of scope, it will attempt to delete the data a second time, which will cause more problems.
What you have implemented there is called fluent interface. I have mostly encountered them in scripting languages, but there is no reason you can't use in C++.
If you really, really hate calling lots of set functions, one after the other, then you may enjoy the following code, For most people, this is way overkill for the 'problem' solved.
This code demonstrates how to create a set function that can accept set classes of any number in any order.
#include "stdafx.h"
#include <stdarg.h>
// Base class for all setter classes
class cSetterBase
{
public:
// the type of setter
int myType;
// a union capable of storing any kind of data that will be required
union data_t {
int i;
float f;
double d;
} myValue;
cSetterBase( int t ) : myType( t ) {}
};
// Base class for float valued setter functions
class cSetterFloatBase : public cSetterBase
{
public:
cSetterFloatBase( int t, float v ) :
cSetterBase( t )
{ myValue.f = v; }
};
// A couple of sample setter classes with float values
class cSetterA : public cSetterFloatBase
{
public:
cSetterA( float v ) :
cSetterFloatBase( 1, v )
{}
};
// A couple of sample setter classes with float values
class cSetterB : public cSetterFloatBase
{
public:
cSetterB( float v ) :
cSetterFloatBase( 2, v )
{}
};
// this is the class that actually does something useful
class cUseful
{
public:
// set attributes using any number of setter classes of any kind
void Set( int count, ... );
// the attributes to be set
float A, B;
};
// set attributes using any setter classes
void cUseful::Set( int count, ... )
{
va_list vl;
va_start( vl, count );
for( int kv=0; kv < count; kv++ ) {
cSetterBase s = va_arg( vl, cSetterBase );
cSetterBase * ps = &s;
switch( ps->myType ) {
case 1:
A = ((cSetterA*)ps)->myValue.f; break;
case 2:
B = ((cSetterB*)ps)->myValue.f; break;
}
}
va_end(vl);
}
int _tmain(int argc, _TCHAR* argv[])
{
cUseful U;
U.Set( 2, cSetterB( 47.5 ), cSetterA( 23 ) );
printf("A = %f B = %f\n",U.A, U.B );
return 0;
}
You may consider the ConstrOpt paradigm. I first heard about this when reading the XML-RPC C/C++ lib documentation here: http://xmlrpc-c.sourceforge.net/doc/libxmlrpc++.html#constropt
Basically the idea is similar to yours, but the "ConstrOpt" paradigm uses a subclass of the one you want to instantiate. This subclass is then instantiated on the stack with default options and then the relevant parameters are set with the "reference-chain" in the same way as you do.
The constructor of the real class then uses the constrOpt class as the only constructor parameter.
This is not the most efficient solution, but can help to get a clear and safe API design.