Which design to chose for complex object initialization? - c++

Lets say I have a class encapsulating one (or multiple) member(s) which must in some way be initialized and there is no reasonable way to use the class without it (so I don't want to make it optional).
Is it then better to have initialization run in its constructor like so:
class MyClass
{
MyClass()
{
if(!obj.initialize()
throw ...;
}
private:
MyObject obj;
}
or would you suggest the following design:
class MyClass
{
MyClass()
{
}
bool initialize()
{
return obj.initialize();
}
private:
MyObject obj;
}
The 1st one looks appealing because I can guarantee all requirements for using my class have been met after the constructor has run and I can report any errors by throwing an exception.
The 2nd looks good because it doesn't overload constructors with stuff that intuitively doesn't belong there, especially once the initialization routine gets complex and i.e. creates widgets, opens database connections, initializes 3rd party libraries etc. In a lot of legacy code I'm working with, ctors are flooded with parameters and intialization stuff, probably running thousands of code lines before this type of bloated object construction is even done. Trying to refactor these into something cleaner is really hard at some point because there are too many dependencies involved. That's what motivated my question.
The big disadvantage of design #2 I can see is that I need a public initialization routine which the client must remember to call. But since this can and probably will be forgotten, I have to track and check intialization state in all public members and somehow treat errors (probably an assert will do). This will also clutter my class with stuff that's not there if I chose design #1.
So what's my best choice here?

"The 1st one looks appealing because I can guarantee all requirements for using my class have been met after the constructor has run ...."
This must be the case otherwise the design is bad.
When the constructor completes then the object must be usable without any undefined behaviour and according to its interface specification.
BUT that does not mean the object needs to be configured for a given purpose.
I like to separate out initialization from configuration.
For example look at std::fstream. You can create a completely initialized fstream object without opening any files:
std::fstream fs; // initialized but not configured
It does not exhibit undefined behaviour and will operate according to its interface specification.
So you can use its interface to configure it to a given purpose - for example to read a specific file:
fs.open("myfile.txt", std::ios::in); // configured
The default constructor should do the absolute minimum to put the object into working order without, necessarily configuring it to a given task.
That being said there is no reason not to have other constructors to make creating configured objects easier:
std::fstream fs("myfile.txt", std::ios::in); // initialized & configured

Move the code from MyObject::initialize to MyObject's constructor (the throw as well, if necessary). Now the implicitly-defined default constructor for MyClass will do the right job.

Related

Should a C++ object always be in a valid state?

Whenever an object is constructed, should the constructor always leave it in an "initialised" state?
For example, if an Image class has two constructors where one takes a file path string, and the other takes no parameters, is it bad practice for the latter to leave the image object in an invalid state?
Assuming the class is written to handle both states.
I ask this because I find it almost necessary to have a default construct in a lot of cases. Especially when an object is a member of a class and you want to initialise it IN the constructor of that class.
EDIT: I am aware of the member initialiser list. I have found a few situations where I would like to construct the object DURING the constructor of the class it is held in, not before. Although, I understand that this could potentially be more dangerous than any other alternative.
It all boils down to the definition of a "valid state": if the methods of your class handle the state when the path is empty, then the state with the empty path is a valid state, and is definitely acceptable.
This may not be optimal from the coding perspective, though, because potentially you might need to add multiple checks for the path to be valid. You can often manage complexity by implementing the State Pattern.
I find it almost necessary to have a default construct in a lot of cases. Especially when an object is a member of a class and you want to initialise it IN the constructor of that class.
You do not need a default constructor in order to initialize an object in the constructor of the class of which it is a member, as long as you construct the dependent in the initialization list.
Your last line:
I ask this because I find it almost necessary to have a default construct in a lot of cases. Especially when an object is a member of a class and you want to initialise it IN the constructor of that class.
Implies that you are not using member initializer lists. You do not need a default constructor in this case. Example:
class Member {
public:
Member(std::string str) { std::cout << str << std::endl; }
};
class Foo {
public:
Foo() : member_("Foo") {}
private:
Member member_;
}
Additionally, your question title and body conflict and the terminology is a bit vague. When constructing, it is usually best to leave the object in a valid and usable state. Sometimes the second aspect (being usable) is less necessary, and many solutions require it. Further, in C++11, moving from an object must leave it in a valid state, but doesn't necessarily (and in many cases shouldn't) leave it in a usable state.
EDIT: To address your concern about doing work in your constructor, consider moving the work to either a static member of the Member class, or a private (static or non-static) function in the owning class:
class Member {
public:
Member(std::string str) { std::cout << str << std::endl; }
};
class Foo {
public:
Foo() : member_(CreateFoo()) {}
private:
Member CreateMember() {
std::string str;
std::cin >> str;
return Member(str);
}
Member member_;
};
One danger of this approach, however, is that the intialization order can be important if you use a non-static member function to do the creation. A static function is much much safer, but you may wish to pass some other pertinent member info. Remember that initialization is done in order of member declaration within the class, NOT initializer list declaration order.
Yes, it should always be valid. However, it is usually not very well defined what makes the object valid. At the very least, the object should be usable in a way without crashing. This, however, does not mean that all operations can be performed on the object, but there should be at least one. In many cases, that's just assignment from another source (e.g. std container iterators) and destruction (this one is mandatory, even after a move). But there more operations the objects supports in any kind of state, the less prone to error it will be.
It is usually a trade-off. If you can get away with objects only having states where all operations are valid, that's certainly great. However, those cases are rare, and if you have to jump through hoops to get there, it's usually easier to just add and document preconditions to some of its functionality. In some cases, you might even split the interface to differentiate between functions that make this trade-off and those that do not. A popular example of this is in std::vector, where you need to have enough elements as a precondition to using operator[]. On the other hand, the at() function will still work, but throw an exception.
First, let us define what exactly a "valid state" is: Its an state where the object could do its work.
For example, if we are writting a class that manages a file and let us to write and read the file, a valid state (following our definition) could be an state where the object is holding a correctly oppened file and its ready to read/write on it.
But consider other situation: Whats the state of a moved rvalue?
File::File( File&& other )
{
_file_handle = other._file_handle;
other._file_handle = nullptr; //Whats this state?
}
Its a state where the file object its not ready to write/read on a file, but is ready to be initialized. That is, is a ready to initialize state.
Now consider an alternative implementation of the above ctor using the copy and swap idiom:
File::File() :
_file_handle{ nullptr }
{}
File::File( File&& other ) : File() //Set the object to a ready to initialice state
{
using std::swap; //Enable ADL
swap( *this , other );
}
Here we use the default ctor to put the object on a ready to initialice state, and just swap the passed rvalue with this object, resulting on exactly the same behaviour as the first implementation.
As we have seen above, one thing is a ready to work state, a state where the object is ready to do whats supposed to do, and other completely different thing is a ready to initialize state: A state where the object is not ready to work, but is ready to be initialized and setted up to work..
My answer to your question is: An object is not alwways in a valid state (Its not allways ready to be used), but if its not ready to be used it should be ready to be initialized and then ready to work.
Normally, yes. I've seen a few good counterexamples but they are so rare.

automatic way to detect objects passed by value to functions in c++

I and my co-coder often forget to pass (large) objects by reference and instead pass by value. This might be hurting performance. Is it possible to configure the compiler to warn me in such cases? Is it possible to detect it automatically in a bunch of c++ source files ... maybe a regex that someone has already written?
UPDATE:
Thanks guys for your helpful answers. One problem with all answers is that they only work for classes I write ... not for existing classes .. like std::vector . I can subclass them, but it would be too tedious
You could declare the copy constructor for the types as private - since the copy ctor is called when passing objects by value, your code will error at compile time at any call-site where you're passing by value.
You can also use the new c++11 support to delete unwanted constructors/destructors, if your compiler supports it. Check out the details here.
If you actually need to use the copy ctor in your code another option is to add a debug break-point within the copy ctor. You can then step through a debug build of your program and check when the copy ctor is called.
Hope this helps.
EDIT: Since you're looking to detect copy-ctor use on the standard containers things are a little less straightforward. You could try something along these lines, which is a super-ugly hack, delegating all std::vector instances through a wrapper class with a disabled copy-ctor.
Note the warnings in the code. I would only use this kind of thing to identify your pass-by-value issues and then delete it - reverting to clean use of std::vector etc.
If you wanted to permanently disable copying of standard containers you could write your own wrapper classes that encapsulate (rather than inherit from) the standard containers.
One way you can do is have your heavy object inherit from class like:
struct heavy {
struct heavy_copy_ctor_invoked {};
heavy(const heavy&) {
typename boost::mpl::print<heavy_copy_ctor_invoked>::type _;
}
};
struct foo : heavy { ...
everytime heavy copy-ctor is called, mpl will throw a warning.
Just make a copy constructor and an operator= of the big object private. In QT they made special macro for that Q_DISABLE_COPY().

Should I use virtual 'Initialize()' functions to initialize an object of my class?

I'm currently having a discussion with my teacher about class design and we came to the point of Initialize() functions, which he heavily promotes. Example:
class Foo{
public:
Foo()
{ // acquire light-weight resources only / default initialize
}
virtual void Initialize()
{ // do allocation, acquire heavy-weight resources, load data from disk
}
// optionally provide a Destroy() function
// virtual void Destroy(){ /*...*/ }
};
Everything with optional parameters of course.
Now, he also puts emphasis on extendability and usage in class hierarchies (he's a game developer and his company sells a game engine), with the following arguments (taken verbatim, only translated):
Arguments against constructors:
can't be overridden by derived classes
can't call virtual functions
Arguments for Initialize() functions:
derived class can completely replace initialization code
derived class can do the base class initialization at any time during its own initialization
I have always been taught to do the real initialization directly in the constructor and to not provide such Initialize() functions. That said, I for sure don't have as much experience as he does when it comes to deploying a library / engine, so I thought I'd ask at good ol' SO.
So, what exactly are the arguments for and against such Initialize() functions? Does it depend on the environment where it should be used? If yes, please provide reasonings for library / engine developers or, if you can, even game developer in general.
Edit: I should have mentioned, that such classes will be used as member variables in other classes only, as anything else wouldn't make sense for them. Sorry.
For Initialize: exactly what your teacher says, but in well-designed code you'll probably never need it.
Against: non-standard, may defeat the purpose of a constructor if used spuriously. More importantly: client needs to remember to call Initialize. So, either instances will be in an inconsistent state upon construction, or they need lots of extra bookkeeping to prevent client code from calling anything else:
void Foo::im_a_method()
{
if (!fully_initialized)
throw Unitialized("Foo::im_a_method called before Initialize");
// do actual work
}
The only way to prevent this kind of code is to start using factory functions. So, if you use Initialize in every class, you'll need a factory for every hierarchy.
In other words: don't do this if it's not necessary; always check if the code can be redesigned in terms of standard constructs. And certainly don't add a public Destroy member, that's the destructor's task. Destructors can (and in inheritance situations, must) be virtual anyway.
I"m against 'double initialization' in C++ whatsoever.
Arguments against constructors:
can't be overridden by derived classes
can't call virtual functions
If you have to write such code, it means your design is wrong (e.g. MFC). Design your base class so all the necessary information that can be overridden is passed through the parameters of its constructor, so the derived class can override it like this:
Derived::Derived() : Base(GetSomeParameter())
{
}
This is a terrible, terrible idea. Ask yourself- what's the point of the constructor if you just have to call Initialize() later? If the derived class wants to override the base class, then don't derive.
When the constructor finishes, it should make sense to use the object. If it doesn't, you've done it wrong.
One argument for preferring initialization in the constructor: it makes it easier to ensure that every object has a valid state. Using two-phase initialization, there's a window where the object is ill-formed.
One argument against using the constructor is that the only way of signalling a problem is through throwing an exception; there's no ability to return anything from a constructor.
Another plus for a separate initialization function is that it makes it easier to support multiple constructors with different parameter lists.
As with everything this is really a design decision that should be made with the specific requirements of the problem at hand, rather than making a blanket generalization.
A voice of dissension is in order here.
You might be working in an environment where you have no choice but to separate construction and initialization. Welcome to my world. Don't tell me to find a different environment; I have no choice. The preferred embodiment of the products I create is not in my hands.
Tell me how to initialize some aspects of object B with respect to object C, other aspects with respect to object A; some aspects of object C with respect to object B, other aspects with respect to object A. The next time around the situation may well be reversed. I won't even get into how to initialize object A. The apparently circular initialization dependencies can be resolved, but not by the constructors.
Similar concerns goes for destruction versus shutdown. The object may need to live past shutdown, it may need to be reused for Monte Carlo purposes, and it might need to be restarted from a checkpoint dumped three months ago. Putting all of the deallocation code directly in the destructor is a very bad idea because it leaks.
Forget about the Initialize() function - that is the job of the constructor.
When an object is created, if the construction passed successfully (no exception thrown), the object should be fully initialized.
While I agree with the downsides of doing initialization exclusively in the constructor, I do think that those are actually signs of bad design.
A deriving class should not need to override base class initialization behaviour entirely. This is a design flaw which should be cured, rather than introducing Initialize()-functions as a workaround.
Not calling Initialize may be easy to do accidentally and won't give you a properly constructed object. It also doesn't follow the RAII principle since there are separate steps in constructing/destructing the object: What happens if Initialize fails (how do you deal with the invalid object)?
By forcing default initialization you may end up doing more work than doing initialization in the constructor proper.
Ignoring the RAII implications, which others have adequately covered, a virtual initialization method greatly complicates your design. You can't have any private data, because for the ability to override the initialization routine to be at all useful, the derived object needs access to it. So now the class's invariants are required to be maintained not only by the class, but by every class that inherits from it. Avoiding that sort of burden is part of the point behind inheritance in the first place, and the reason constructors work the way they do with regard to subobject creation.
Others have argued at length against the use of Initialize, I myself see one use: laziness.
For example:
File file("/tmp/xxx");
foo(file);
Now, if foo never uses file (after all), then it's completely unnecessary to try and read it (and would indeed be a waste of resources).
In this situation, I support Lazy Initialization, however it should not rely on the client calling the function, but rather each member function should check if it is necessary to initialize or not. In this example name() does not require it, but encoding() does.
Only use initialize function if you don't have the data available at point of creation.
For example, you're dynamically building a model of data, and the data that determines the object hierarchy must be consumed before the data that describes object parameters.
If you use it, then you should make the constructor private and use factory methods instead that call the initialize() method for you. For example:
class MyClass
{
public:
static std::unique_ptr<MyClass> Create()
{
std::unique_ptr<MyClass> result(new MyClass);
result->initialize();
return result;
}
private:
MyClass();
void initialize();
};
That said, initializer methods are not very elegant, but they can be useful for the exact reasons your teacher said. I would not consider them 'wrong' per se. If your design is good then you probably will never need them. However, real-life code sometimes forces you to make compromises.
Some members simply must have values at construction (e.g. references, const values, objects designed for RAII without default constructors)... they can't be constructed in the initialise() function, and some can't be reassigned then.
So, in general it's not a choice of constructor vs. initialise(), it's a question of whether you'll end up having code split between the two.
Of bases and members that could be initialised later, for the derived class to do it implies they're not private; if you go so far as to make bases/members non-private for the sake of delaying initialisaton you break encapsulation - one of the core principles of OOP. Breaking encapsulation prevents base class developer(s) from reasoning about the invariants the class should protect; they can't develop their code without risking breaking derived classes - which they might not have visibility into.
Other times it's possible but sometimes inefficient if you must default construct a base or member with a value you'll never use, then assign it a different value soon after. The optimiser may help - particularly if both functions are inlined and called in quick succession - but may not.
[constructors] can't be overridden by derived classes
...so you can actually rely on them doing what the base class needs...
[constructors] can't call virtual functions
The CRTP allows derived classes to inject functionality - that's typically a better option than a separate initialise() routine, being faster.
Arguments for Initialize() functions:
derived class can completely replace initialization code
I'd say that's an argument against, as above.
derived class can do the base class initialization at any time during its own initialization
That's flexible but risky - if the base class isn't initialised the derived class could easily end up (due to oversight during the evolution of the code) calling something that relies on that base being initialised and consequently fails at run time.
More generally, there's the question of reliable invocation, usage and error handling. With initialise, client code has to remember to call it with failures evident at runtime not compile time. Issues may be reported using return types instead of exceptions or state, which can sometimes be better.
If initialise() needs to be called to set say a pointer to nullptr or a value safe for the destructor to delete, but some other data member or code throws first, all hell breaks loose.
initialise() also forces the entire class to be non-const in the client code, even if the client just wants to create an initial state and ensure it won't be further modified - basically you've thrown const-correctness out the window.
Code doing things like p_x = new X(values, for, initialisation);, f(X(values, for initialisation), v.push_back(X(values, for initialisation)) won't be possible - forcing verbose and clumsy alternatives.
If a destroy() function is also used, many of the above problems are exacerbated.

Constructors accepting string reference. Bad idea?

It's considered a bad idea/bad design, have a class with a constructor accepting a reference, like the following?
class Compiler
{
public:
Compiler( const std::string& fileName );
~Compiler();
//etc
private:
const std::string& m_CurrentFileName;
};
or should I use values?
I actually do care about performance.
If you used a value parameter in this case, you would have a reference in the class to a temporary, which would become invalid at some point in the future.
The bad idea here is probably storing a reference as a member in the class. It is almost always simpler and more correct to store a value. And in that case, passing the constructor a const reference is the right thing to do.
And as for performance, you should only care about this where it matters, which you can only find out by profiling your code. You should always write your code firstly for correctness, secondly for clarity and lastly for performance.
It's fine as long as the constructor either just uses it without retaining it, copies it for further use (at which point, using a reference probably doesn't matter), or assumes ownership of it (which is iffy because you're depending on the user to behave correctly and not use the string reference further).
However, in most cases, the string copy probably won't be a bottleneck and should be preferred for bug avoidance reasons. If, later, you can PROVE that it's a bottleneck (using profiling, for instance), you might want to think about fixing it.
If you can guarantee that the string that the reference uses won't go out of scope until the class does, then it is maybe Ok to use (I wouldn't). If you were having issues, you may be better passing the string around with a reference counted smart pointer.
It may be worth, and safer, writing your application so that the class constructor copies the string, then when you have performance issues, profile them. Most of the time it is not this sort of thing that causes the issues, but at the algorithm and data structure level.
While passing the parameter via a const reference is a nice thing (you should do that in most cases), storing it as a const reference is dangerous -- if the object passed ceases to exits, you might get a segfault.
Also remember -- premature optimization is the root of all evil! If you have performance issues after writing working code, use a tool like gprof to find where the bottleneck is. And from experience I can tell that the bottleneck almost always will be in bad design, and not a bad language use.
I agree with other people that you should be more concerned about correctness and robustness over performance (so the member variable should be a copy, not a reference) and that if you're really concerned about performance, you should profile your code.
That said, it's not always clear-cut that passing by const reference is faster. For example, if you pass by value instead and if the argument is an rvalue, the compiler can do copy elision (see http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/) and avoid an extra copy when you save it to the member variable. (This isn't very intuitive, and it's probably not something you'd want to do everywhere, so again: profile!)
If you are writing a compiler, copying the filename once or twice will not be the bottleneck. This is more of a C++ style issue, which I leave to the more C++ savvy people around here.
Your class must be self-contained, and avoid unnecessary dependencies. In your example, your "Compiler" class will depend on the CurrentFileName string for its whole existence. Meaning that if CurrentFileName is destroyed before Compiler, you'll have a problem.
Dependents & Managers
So, I guess is depends on the nature of the dependency between the Dependent class and it Manager class (i.e. the Dependent class depends on the Manager class, or, in your example, the Compiler class depends on the std::string class)...
If the dependency is "soft", then Dependant should make a copy of Manager class.
If the dependency is "strong", then Dependant could have a reference to the Manager class.
Soft vs. Strong
An example of "soft dependency" is when your Dependant needs only a value, not the exact object itself. A string is usually seen as a value.
An example of "strong dependency" is when your Dependant needs to have access to its Manager, or when rhe Dependent has no meaning without a Manager (i.e. if the Manager is destroyed, then all Dependents should have been destroyed before)
Conclusion
Usually, the dependency is soft.
If in doubt, considers it soft. You'll have less problems (this is one of the way to have a pretty C++ segfault without pointer arithmetics), and still have the possibility of optimize it if needed.
About your case: Soft
Do yourself a favor, and make a copy of the value.
Optimization is the root of all evil, and unless your profiler says the copy of the string is a problem, then, make a copy, as below:
class Compiler
{
public:
Compiler( const std::string& fileName ); // a reference
~Compiler();
//etc
private:
const std::string m_CurrentFileName; // a value
};
Compiler::Compiler(const std::string& fileName )
: m_CurrentFileName(fileName) // copy of the filename
{
}
About my case: Strong
Now, you could be in a situation where the Dependent's existence has no meaning without the Manager itself.
I work currently on code where the user creates Notifier objects to subscribe to events, and retrieve them when needed. The Notifier object is attached to a Manager at construction, and cannot be detached from it.
It is a design choice to impose to the library user the Manager outlives the Notifier. This means the following code:
Manager manager ;
Notifier notifier(manager) ; // manager is passed as reference
The Notifier code is quite similar to the code you proposed:
class Notifier
{
public :
Notifier(Manager & manager) : m_manager(manager) {}
private :
Manager & m_manager ;
} ;
If you look closely at the design, the m_manager is used as an immutable pointer to the Manager object. I use the C++ reference to be sure:
The reference is defined at construction, and won't ever be changed
The reference is never supposed to be NULL or invalid
This is part of the contract.
If you are highly concerned about performance then passing by reference is the better approach .
Think about following example to make picture more clear:
class A{
public : A() {}
};
class B : public A{
public : B() {}
};
class MyClass{
B bObj;
public:
MyClass(B b) : bObj(b) { } // constructor and destructor overhead
MyClass(B &b) { }
};

How can a member know in what class instance it is constructed?

class C {
public
T x;
};
Is there an elegant way for the constructor of x to know implicitly in what instance of C it is constructing?
I've implemented such behavior with some dirty inelegant machinery. I need this for my sqlite3 wrapper. I don't like all wrappers I've seen, their API IMO ugly and inconvenient. I want something like this:
class TestRecordset: public Recordset {
public:
// The order of fields declarations specifies column index of the field.
// There is TestRecordset* pointer inside Field class,
// but it goes here indirectly so I don't have to
// re-type all the fields in the constructor initializer list.
Field<__int64> field1;
Field<wstring> field2;
Field<double> field3;
// have TestRecordset* pointer too so only name of parameter is specified
// in TestRecordset constructor
Param<wstring> param;
virtual string get_sql() {
return "SELECT 1, '1', NULL FROM test_table WHERE param=:PARAM";
}
// try & unlock are there because of my dirty tricks.
// I want to get rid of them.
TestRecordset(wstring param_value)
try : Recordset(open_database(L"test.db")), param("PARAM") {
param = param_value;
// I LOVE RAII but i cant use it here.
// Lock is set in Recordset constructor,
// not in TestRecordset constructor.
unlock(this);
fetch();
} catch(...) {
unlock(this);
throw;
}
};
I want to clarify the fact - it is a part of the working code. You can do this in C++. I just want to do it in a more nice way.
I've found a way to get rid of unlock and try block. I've remembered there is such a thing as thread local storage. Now I can write constructor as simple as that:
TestRecordset(wstring param_value):
Recordset(open_database(L"test.db")), param("PARAM") {
param = param_value;
fetch();
}
to dribeas:
My objective is to avoid redundant and tedious typing. Without some tricks behind the scene I will have to type for each Field and Param:
TestRecordset(wstring param_value): Recordset(open_database(L"test.db")), param(this, "PARAM"),
field1(this, 0), field2(this, 1), field3(this, 2) { ... }
It is redundant, ugly and inconvenient. For example, if I'll have to add new field in the
middle of SELECT I'll have to rewrite all the column numbers.
Some notes on your post:
Fields and Params are initialized by their default constructors.
Order of initializers in constructor is irrelevant. Fields are always initialized in order of their declaration. I've used this fact to track down column index for fields
Base classes are constructed first. So when Fields are constructed internal field list in Recordset are ready to use by Filed default constructor.
I CAN'T use RAII here. I need to acquire lock in Recorset constructor and release it obligatory in TestRecordset constructor after all Fields are constructed.
No. Objects aren't supposed to need to know where they're being used from in order to work. As far as x is concerned, it's an instance of T. That's it. It doesn't behave differently according to whether it's a member of class C, a member of class D, an automatic, a temporary, etc.
Furthermore, even if the T constructor did know about the instance of C, that instance of C would be incomplete since of course it has not finished construction yet, because its members haven't been constructed. C++ offers you plenty of chances to shoot yourself in the foot, but offering you a reference to an incomplete object in another class's constructor isn't one of them.
The only thing I can think of to approximate your code example is to do something like
#define INIT_FIELDS field1(this), field2(this), field3(this)
immediately after the list of fields, then use INIT_FIELDS in the initializer list and #undef it. It's still duplication, but at least it's all in one place. This will probably surprise your colleagues, however.
The other way to make sure you don't forget a field is to remove the zero-arg constructor from Field. Again, you still have to do the typing, but at least if you forget something the compiler will catch it. The non-DRY nature of initializer lists is, I think, something C++ just has to live with.
Adding on to One by One's answer, the actual question you should be asking is: "what is wrong with my solution design that it requires objects to know where they are instanciated?"
I don't think so.
Out of pure curiosity, why should it matter ? do you have a context in which this can be useful?
M.
I experiment with things like this in C# all the time - I use reflection to do it.
Consider getting a reflection or code generation library for C++ to help you do what you want to.
Now, I can't tell you how to find a good reflection or code generation library for C++, but that's a different question!
I am interested in your code. You comment that all fields plus the param attribute have pointers back into the TestRecordSet but that they don't need to be initialized? Or is it the object of the question, how to avoid having to pass the this pointers during construction?
If what you want is avoid adding all fields in the initialization list of your constructor, then it is a flawed objective. You should always initialize all your members in the initialization list and do so in the same order that they are declared in the class (this is not language enforced, but more of a globally learnt experience).
Your use of the try constructor block is just about he only recommended usage for that functionality (Anyone interested read GOTW#66) if it is indeed required. If the RecordSet member has been constructed (and thus the lock acquired) and something goes wrong afterwards in the constructor then [see quote below] the RecordSet will be destroyed and if it uses RAII internally it will free the lock, so I believe that the try/catch may not really be required.
C++03, 15.2 Exception Handling / Constructors and destructors
An object that is partially
constructed or partially destroyed
will have destructors executed for all
of its fully constructed subobjects,
that is, for subobjects for which the
constructor has completed execution
and the destructor has not yet begun
execution.