Default assignment operator in inner class with reference members - c++

I've run into an issue I don't understand and I was hoping someone here might provide some insight. The simplified code is as follows (original code was a custom queue/queue-iterator implementation):
class B
{
public:
B() {};
class C
{
public:
int get();
C(B&b) : b(b){};
private:
B& b;
};
public:
C get_c() { return C(*this); }
};
int main()
{
B b;
B::C c = b.get_c();
c = b.get_c();
return EXIT_SUCCESS;
}
This, when compiled, gives me the following error:
foo.cpp: In member function 'B::C& B::C::operator=(const B::C&)':
foo.cpp:46: error: non-static reference member 'B& B::C::b', can't use default assignment operator
foo.cpp: In function 'int main()':
foo.cpp:63: note: synthesized method 'B::C& B::C::operator=(const B::C&)' first required here
I can go around this by using two separate C variables, as they are supposed to be independent 'C' objects, but this only hides the problem (I still don't understand why I can't do this).
I think the reason is that the reference cannot be copied, but I don't understand why. Do I need to provide my own assignment operator and copy constructor?

This problem has nothing to do with inner classes. In C++ you just can't (re)assign references - they need to be initialised when defined.
A simpler example is:
class B
{
public:
B(int& i) : ir(i) {};
int& ir;
};
int main()
{
int i;
B b(i); // Constructor - OK
int j;
B bb = B(j); // Copy constructor - OK
bb = b; // Assignment - Error
return 0;
}

A reference cannot be changed after being given its initial value. This means that it is impossible to write an assignment operator that changes the value of a reference member. If you need to do this, use a pointer instead of a reference.

Actually, there's a solution to this. You can implement operator= in terms of copy construction, and it will work :) It's a very capable technique for such cases. Assuming you do want to support assignment.

C++ doesn't have "inner classes", just nested class declarations. "inner classes" are a Java-ism that I don't think are found in other mainstream languages. In Java, inner classes are special because they contain an implicit immutable reference to an object of the containing type. To achieve the equivalent to C++'s nested declarations in Java requires use of static inner classes; static inner classes do not contain a reference to an object of the declaring type.

Related

Detect assignment of base class to reference pointing at derived class

I'm currently investigating the interplay between polymorphic types and assignment operations. My main concern is whether or not someone might try assigning the value of a base class to an object of a derived class, which would cause problems.
From this answer I learned that the assignment operator of the base class is always hidden by the implicitely defined assignment operator of the derived class. So for assignment to a simple variable, incorrect types will cause compiler errors. However, this is not true if the assignment occurs via a reference:
class A { public: int a; };
class B : public A { public: int b; };
int main() {
A a; a.a = 1;
B b; b.a = 2; b.b = 3;
// b = a; // good: won't compile
A& c = b;
c = a; // bad: inconcistent assignment
return b.a*10 + b.b; // returns 13
}
This form of assignment would likely lead to inconcistent object state, however there is no compiler warning and the code looks non-evil to me at first glance.
Is there any established idiom to detect such issues?
I guess I only can hope for run-time detection, throwing an exception if I find such an invalid assignment. The best approach I can think of just now is a user-defined assigment operator in the base class, which uses run-time type information to ensure that this is actually a pointer to an instance of base, not to a derived class, and then does a manual member-by-member copy. This sounds like a lot of overhead, and severely impact code readability. Is there something easier?
Edit: Since the applicability of some approaches seems to depend on what I want to do, here are some details.
I have two mathematical concepts, say ring and field. Every field is a ring, but not conversely. There are several implementations for each, and they share common base classes, namely AbstractRing and AbstractField, the latter derived from the former. Now I try to implement easy-to-write by-reference semantics based on std::shared_ptr. So my Ring class contains a std::shared_ptr<AbstractRing> holding its implementation, and a bunch of methods forwarding to that. I'd like to write Field as inheriting from Ring so I don't have to repeat those methods. The methods specific to a field would simply cast the pointer to AbstractField, and I'd like to do that cast statically. I can ensure that the pointer is actually an AbstractField at construction, but I'm worried that someone will assign a Ring to a Ring& which is actually a Field, thus breaking my assumed invariant about the contained shared pointer.
Since the assignment to a downcast type reference can't be detected at compile time I would suggest a dynamic solution. It's an unusual case and I'd usually be against this, but using a virtual assignment operator might be required.
class Ring {
virtual Ring& operator = ( const Ring& ring ) {
/* Do ring assignment stuff. */
return *this;
}
};
class Field {
virtual Ring& operator = ( const Ring& ring ) {
/* Trying to assign a Ring to a Field. */
throw someTypeError();
}
virtual Field& operator = ( const Field& field ) {
/* Allow assignment of complete fields. */
return *this;
}
};
This is probably the most sensible approach.
An alternative may be to create a template class for references that can keep track of this and simply forbid the usage of basic pointers * and references &. A templated solution may be trickier to implement correctly but would allow static typechecking that forbids the downcast. Here's a basic version that at least for me correctly gives a compilation error with "noDerivs( b )" being the origin of the error, using GCC 4.8 and the -std=c++11 flag (for static_assert).
#include <type_traits>
template<class T>
struct CompleteRef {
T& ref;
template<class S>
CompleteRef( S& ref ) : ref( ref ) {
static_assert( std::is_same<T,S>::value, "Downcasting not allowed" );
}
T& get() const { return ref; }
};
class A { int a; };
class B : public A { int b; };
void noDerivs( CompleteRef<A> a_ref ) {
A& a = a_ref.get();
}
int main() {
A a;
B b;
noDerivs( a );
noDerivs( b );
return 0;
}
This specific template can still be fooled if the user first creates a reference of his own and passes that as an argument. In the end, guarding your users from doing stupid things is an hopeless endeavor. Sometimes all you can do is give a fair warning and present a detailed best-practice documentation.

c++ variable assignment, is this a normal way..?

This may be a silly question, but still I'm a bit curious...
Recently I was working on one of my former colleague projects, and I've noticed that he really loved to use something like this:
int foo(7);
instead of:
int foo = 7;
Is this a normal/good way to do in C++ language?
Is there some kind of benefits to it? (Or is this just some silly programming style that he was into..?)
This really reminds me a bit of a good way how class member variables can be assigned in the class constructor... something like this:
class MyClass
{
public:
MyClass(int foo) : mFoo(foo)
{ }
private:
int mFoo;
};
instead of this:
class MyClass
{
public:
MyClass(int foo)
{
mFoo = foo;
}
private:
int mFoo;
};
For basic types there's no difference. Use whichever is consistent with the existing code and looks more natural to you.
Otherwise,
A a(x);
performs direct initialization, and
A a = x;
performs copy initialization.
The second part is a member initializer list, there's a bunch of Q&As about it on StackOverflow.
Both are valid. For builtin types they do the same thing; for class types there is a subtle difference.
MyClass m(7); // uses MyClass(int)
MyClass n = 3; // uses MyClass(int) to create a temporary object,
// then uses MyClass(const MyClass&) to copy the
// temporary object into n
The obvious implication is that if MyClass has no copy constructor, or it has one but it isn't accessible, the attempted construction fails. If the construction would succeed, the compiler is allowed to skip the copy constructor and use MyClass(int) directly.
All the answers above are correct. Just add that to it that C++11 supports another way, a generic one as they say to initialize variables.
int a = {2} ;
or
int a {2} ;
Several other good answers point out the difference between constructing "in place" (ClassType v(<constructor args>)) and creating a temporary object and using the copy constructor to copy it (ClassType v = <constructor arg>). Two additional points need to be made, I think. First, the second form obviously has only a single argument, so if your constructor takes more than one argument, you should prefer the first form (yes, there are ways around that, but I think the direct construction is more concise and readable - but, as has been pointed out, that's a personal preferance).
Secondly, the form you use matters if your copy constructor does something significantly different than your standard constructor. This won't be the case most of the time, and some will argue that it's a bad idea to do so, but the language does allow for this to be the case (all surprises you end up dealing with because of it, though, are your own fault).
It's a C++ style of initializing variables - C++ added it for fundamental types so the same form could be used for fundamental and user-defined types. this can be very important for template code that's intended to be instantiated for either kind of type.
Whether you like to use it for normal initialization of fundamental types is a style preference.
Note that C++11 also adds the uniform initialization syntax which allows the same style of initialization to be used for all types - even aggregates like POD structs and arrays (though user defined types may need to have a new type of constructor that takes an initialization list to allow the uniform syntax to be used with them).
Yours is not a silly question at all as things are not as simple as they may seem. Suppose you have:
class A {
public:
A() {}
};
and
class B {
public:
class B(A const &) {}
};
Writing
B b = B(A());
Requires that B's copy constructor be accessible. Writing
B b = A();
Requires also that B's converting constructor B(A const &) be not declared explicit. On the other hand if you write
A a;
B b(a);
all is well, but if you write
B b(A());
This is interpreted by the compiler as the declaration of a function b that takes a nameless argument which is a parameterless function returning A, resulting in mysterious bugs. This is known as C++'s most vexing parse.
I prefer using the parenthetical style...though I always use a space to distinguish from function or method calls, on which I don't use a space:
int foo (7); // initialization
myVector.push_back(7); // method call
One of my reasons for preferring using this across the board for initialization is because it helps remind people that it is not an assignment. Hence overloads to the assignment operator will not apply:
#include <iostream>
class Bar {
private:
int value;
public:
Bar (int value) : value (value) {
std::cout << "code path A" << "\n";
}
Bar& operator=(int right) {
value = right;
std::cout << "code path B" << "\n";
return *this;
}
};
int main() {
Bar b = 7;
b = 7;
return 0;
}
The output is:
code path A
code path B
It feels like the presence of the equals sign obscures the difference. Even if it's "common knowledge" I like to make initialization look notably different than assignment, since we are able to do so.
It's just the syntax for initialization of something :-
SomeClass data(12, 134);
That looks reasonable, but
int data(123);
Looks strange but they are the same syntax.

C++: when we should use "this->" PLUS parameters by reference

suppose we have a class
class Foo {
private:
int PARTS;
public:
Foo( Graph & );
int howBig();
}
int Foo::howBig() { return this->PARTS; }
int Foo::howBig() { return PARTS;       }
Foo::Foo( Graph &G ) {
<Do something with G.*>
}
Which one of howBig()-variants is correct?
The &-sign ensures that only the reference for Graph object
is passed to initialization function?
In C I would simply do something like some_function( Graph *G ),
but in C++ we have both & and *-type variables, never understood
the difference...
Thank you.
When you've local variable inside a member function, then you must have to use this as:
Foo::MemberFunction(int a)
{
int b = a; //b is initialized with the parameter (which is a local variable)
int c = this->a; //c is initialized with member data a
this->a = a; //update the member data with the parameter
}
But when you don't have such cases, then this is implicit; you need to explicity write it, which means in your code, both versions of howBig is correct.
However, in member initialization list, the rules are different. For example:
struct A
{
int a;
A(int a) : a(a) {}
};
In this code, a(a) means, the member data a is being initialized with the parameter a. You don't have to write this->a(a). Just a(a) is enough. Understand this visually:
A(int a) : a ( a ) {}
// ^ ^
// | this is the parameter
// this is the member data
You can use this-> to resolve the dependent name issue without explicitly having to spell out the name of the base. If the name of the base is big this could arguably improve readability.
This issue only occurs when writing templates and using this-> is only appropriate if they're member functions, e.g.:
template <typename T>
struct bar {
void func();
};
template <typename T>
struct foo : public bar {
void derived()
{
func(); // error
this->func(); // fine
bar<T>::func(); // also fine, but potentially a lot more verbose
}
};
Which one of howBig()-variants is correct?
both in your case, the compiler will produce the same code
The &-sign ensures that only the reference for Graph object is passed to initialization function? In C I would simply do something like some_function( Graph *G ), but in C++ we have both & and *-type variables, never understood the difference...
there is no difference as per the use of the variable inside the method(except syntax) - in the case of reference(&) imagine as if you've been passed an invisible pointer that you can use without dereferencing
it(the &) might be "easier" for clients to use
Both forms of Foo::howBig() are correct. I tend to use the second in general, but there are situations that involve templates where the first is required.
The main difference between references and pointers is the lack of "null references". You can use reference arguments when you don't want to copy the whole object but you want to force the caller to pass one.
Both are correct. Usually shorter code is easier to read, so only use this-> if you need it to disambiguate (see the other answers) or if you would otherwise have trouble understanding where the symbol comes from.
References can't be rebound and can't be (easily) bound to NULL, so:
Prefer references to pointers where you can use them. Since they cannot be null and they cannot be deleted, you have fewer things to worry about when using code that uses references.
Use const references instead of values to pass objects that are large (more than say 16 or 20 bytes) or have complex copy constructors to save copy overhead while treating it as if it was pass by value.
Try to avoid return arguments altogether, whether by pointer or reference. Return complex object or std::pair or boost::tuple or std::tuple (C++11 or TR1 only) instead. It's more readable.

How to prevent default initialization of a const variable with a class type

I have a custom class that I want to behave like a built-in type.
However I have noticed that you can initialise a const variable of that class without providing an initial value. My class currently has an empty default constructor.
Here is a comparison of int and my class foo:
int a; // Valid
int a = 1; // Valid
const int a = 1; // Valid
const int a; // Error
foo a; // Valid
foo a = 1; // Valid
const foo a = 1; // Valid
const foo a; // Should cause an error, but it compiles
As you can see I need to prevent
const foo a;
from compiling.
Any ideas from C++ gurus?
It compiles only if it has a default constructor, and it compiles because it has it, which means that it is initialized. If you don't want that line to compile, just disable the default constructor (will also make foo a; an error as an unwanted side effect). Without a definition of foo or what you want to do, this is as far as I can get.
I don't think there is any way of achieving what you want (i.e. allow the non-const variable to be default initialized, while having the const version fail compilation and allowing the other use cases --that require providing constructors)
The rules of C++ simply say that default-initialization (e.g. new T;) and value-initialization (e.g. new T();) are the same for objects of class type, but not for objects of fundamental type.
There's nothing you can do to "override" this distinction. It's a fundamental part of the grammar. If your class is value-initializable, then it is also default-initializable.
There is a sort-of exception for classes without any user-defined constructors: In that case, initialization of members is done recursively (so if you default-init the object, it tries to default-init all members), and this will fail if any of the class members are themselves fundamental, or again of this nature.
For example, consider the following two classes:
struct Foo { int a; int b; };
struct Goo { int a; int b; Goo(){} };
//const Foo x; // error
const Goo y; // OK
The implicit constructor for Foo is rejected because it doesn't initialize the fundamental members. However, y is happily default-initialized, and y.a and y.b are now "intentionally left blank".
But unless your class doesn't have any user-defined constructors, this information won't help you. You cannot "forward" the initialization type to a member (like Foo() : INIT_SAME_AS_SELF(a), b() { }).

C++: Is it possible to call an object's function before constructor completes?

In C++, is it possible to call a function of an instance before the constructor of that instance completes?
e.g. if A's constructor instantiates B and B's constructor calls one of A's functions.
Yes, that's possible. However, you are responsible that the function invoked won't try to access any sub-objects which didn't have their constructor called. Usually this is quite error-prone, which is why it should be avoided.
This is very possible
class A;
class B {
public:
B(A* pValue);
};
class A {
public:
A() {
B value(this);
}
void SomeMethod() {}
};
B::B(A* pValue) {
pValue->SomeMethod();
}
It's possible and sometimes practically necessary (although it amplifies the ability to level a city block inadvertently). For example, in C++98, instead of defining an artificial base class for common initialization, in C++98 one often see that done by an init function called from each constructor. I'm not talking about two-phase construction, which is just Evil, but about factoring out common initialization.
C++0x provides constructor forwarding which will help to alleviate the problem.
For the in-practice it is Dangerous, one has to be extra careful about what's initialized and not. And for the purely formal there is some unnecessarily vague wording in the standard which can be construed as if the object doesn't really exist until a constructor has completed successfully. However, since that interpretation would make it UB to use e.g. an init function to factor out common initialization, which is a common practice, it can just be disregarded.
why would you wanna do that? No, It can not be done as you need to have an object as one of its parameter(s). C++ member function implementation and C function are different things.
c++ code
class foo
{
int data;
void DoSomething()
{
data++;
}
};
int main()
{
foo a; //an object
a.data = 0; //set the data member to 0
a.DoSomething(); //the object is doing something with itself and is using 'data'
}
Here is a simple way how to do it C.
typedef void (*pDoSomething) ();
typedef struct __foo
{
int data;
pDoSomething ds; //<--pointer to DoSomething function
}foo;
void DoSomething(foo* this)
{
this->data++; //<-- C++ compiler won't compile this as C++ compiler uses 'this' as one of its keywords.
}
int main()
{
foo a;
a.ds = DoSomething; // you have to set the function.
a.data = 0;
a.ds(&a); //this is the same as C++ a.DoSomething code above.
}
Finally, the answer to your question is the code below.
void DoSomething(foo* this);
int main()
{
DoSomething( ?? ); //WHAT!?? We need to pass something here.
}
See, you need an object to pass to it. The answer is no.