I have written two custom classes, called A and B
My B class has a member variable a, and it has a function:
void B::setA(A s)
{
a = s;
}
However, this line is giving me an error:
'operator =' function is unavailable in 'A'.
From my understanding, this means somehow the compiler is not creating a default copy assignment function for my A class. However, I don't see why... the only constructor I've written in A looks like...
class A
{
//...
public:
A() {};
//...
};
Now in truth, A and B are large classes with a lot of member variables, and the names aren't really A and B. Short of posting the entire source for both of these classes, could anyone tell me what types of things I might look for when trying to diagnose that error message? Just to be clear, I never use pointers or low-level features like that so, as far as I know, the default copy-assignment should work fine for class A.
edit:
Someone mentioned that one of the member variables of A might be to blame, so here are all of the types:
const std::string
static const bool
static std::map<int,std::string>
std::vector
std::map<int, C>
where C is a struct that I defined in the same header file that A is in. It just contains a few integers and strings.
You have in class A a non-static data member declared as
const std::string
that is with the qualifier const. In this case the implicit copy assignment operator is defined by the compiler as deleted.
const members don't mix well with copy assignment operators. Not only won't the compiler generate one for you, it would also be semantically hard to come up with an "assignment" which does not actually assign everything.
Nothing stops you from writing an assignment operator which does not assign to your const member, of course, but that would mean one of two things:
The assigned object does not appear to the client as an identical copy of the source, which is not what one would except from a copy assignment operator, so that would be a case of operator-overloading abuse.
The member variable does not have an observable effect to the outside. In that case, one must wonder why it exists in the first place, or rather why it is not mutable rather than const.
Related
I want to detect during compile time (static assertion) whether a class meets both the following conditions:
Has an implicit default constructor (i.e., no user-defined default constructor).
Has at least one data member which is a pod (i.e., a member whose default initialization is to assume whatever random bytes was in its memory address).
[I hope I used the term pod correctly here]
The idea is to avoid working with objects with uninitialized members. I know there are different methods to do this during coding, but I also want a mechanism to detect this during compilation.
I tried using different std/boost functions, such as is_trivially_constructible, is_pod, but none of these provide the exact terms I need.
For example, let's say I have the following classes:
struct A
{
int a;
}
struct B
{
int* b;
}
struct C
{
bool c;
std::string c_str_;
}
struct D
{
D();
float d;
}
struct E
{
std::string e;
}
Assuming the function I need is called "has_primitive_and_implicit_ctor", I would like the output for each call to be as in the comments:
has_primitive_and_implicit_ctor<A>(); //true - A has at least one pod type member (int)
has_primitive_and_implicit_ctor<B>(); //true - A has at least one pod type member (pointer)
has_primitive_and_implicit_ctor<C>(); //true - A has at least one pod type member (bool), even though there is one non-pod member
has_primitive_and_implicit_ctor<D>(); //false - has a pod member(float), but a user defined ctor
has_primitive_and_implicit_ctor<E>(); //false - doesn't have a default ctor but has no pod members
Firstly, it seems to me like a broken design to expect from the user of a class to care about its member initialisation. You should make sure in the class itself that all its members are initialised, not somewhere else where it is used.
What you are looking for does not exist, and if it would, it would not even help you. The existence of an explicit constructor does not guarantee that a data member is initialised. On the other hand, with C++11 it is even possible to initialise data members without explicitly writing a constructor (using the brace syntax in the class declaration). Also you just seem to care about uninitialised POD members, but what about uninitialised non-POD members?
That said, compiler can generate warnings about uninitialised values, but often you have to enable this warning (e.g. -Wuninitialized option for gcc). Most compilers allow to force treating warnings as an error. In combination this can give you the desired effect even without specifically writing code to test for it, and it would also work for any uninitialised values, not only those in classes. Maybe this is the solution you are looking for.
I'm writing a class that has one public static method and a few private methods in C++. Does it make any sense to explicitly delete (see code below) the copy and assignment operators in this case?
public:
static MyReturnType* CreateSomeMock(const myType input);
MyClass(const MyClass&) = delete;
MyClass& operator=(const MyClass&) = delete;
private:
static ...
I'm inclined to say that I shouldn't worry about someone trying to copy or assign to a default constructed class with no instance variables. I'm just not 100% and am curious what the community thinks is a best practice.
UPDATE 1
I've moved the private methods to just be non-member functions defined in the .cpp file. The header still contains the public member function CreateSomeMock and I'm still curious about the assignment/copy-construction =).
UPDATE 2
This "class" is essentially a namespace. I appreciate all the answers around this point and also want to keep this on topic of the = delete part of the question in this case (which I agree at this point should really be avoided...but I'm case-in-point that it happens sometimes).
The only difference between a class with one (or more) static functions, and a few functions within namespaces is when you use templates: you can use the class as a template parameter, but not a namespace.
Alternatively, you could use the static method as the template parameter, but that won't scale when you add more method to your class or namespace.
E.g. if you have:
class X {
public:
static void a();
static void b();
};
You can use it in a template as some_template<X>, and your templates could call a and b on the template parameter:
template<typename T>
void some_template() { T::a(); T::b(); }
But if X is a namespace, you would need two template parameters
: some_template<X::a, X::b>
If this is a valid use case, so you really do need a static class, you probably want to avoid accidentally creating an instance of it.
A practical reason for that is that in C++, every object requires a size bigger than zero: when somebody accidentally creates an instance of this class, it will have a cost, even if minimal.
It cant hurt to delete them, this way a default one wont be created for you by the compiler. You should however follow the rule of 3 and explicitly declare the destructor (not that it matters).
This class is then pretty pointless though. It seems like you should instead declare non-member functions as part of a namespace:
namespace myFactoryPattern {
MyReturnType* CreateSomeMock(const myType input);
This pattern is called static class. It differs from a namespace (which you might consider as an alternative) in that a template can be specialized over it. It's expected, but not required that you delete: (either in the class, or a base class)
Default, copy and move constructors
Copy and move assignment
Or, alternatively you might delete:
Destructor (disallowing non-pointers and delete)
operator new(size_t) and operator new[](size_t) (disallowing new to a naked pointer that's never deleted)
The latter has the fun factor of surprising everyone and stealing hours from their time to understand what's going on and why they cannot create and instance.
Or - you might just allow instances. It really hurts no-one, experienced programmers won't create any; but you might still pass it to template functions that expect a member to be passed given your static methods fulfil the interface required.
Rather surprised to find this question not asked before. Actually, it has been asked before but the questions are VERY DIFFERENT to mine. They are too complicated and absurd while I'll keep it simple and to the point. That is why this question warrants to be posted.
Now, when I do this,
struct A {
int a = -1;
};
I get the following error:
ANSI C++ forbids in-class initialization of non-const static member a
Now, along with the workaround can someone please tell me THE BEST way of initializing a struct member variable with a default value?
First, let's look at the error:
ANSI C++ forbids in-class initialization of non-const static member a
Initialization of a true instance member, which resides within the memory of an instance of your struct is the responsibility of this struct's constructor.
A static member, though defined inside the definition of a particular class/struct type, does not actually reside as a member of any instances of this particular type. Hence, it's not subject to explaining which value to assign it in a constructor body. It makes sense, we don't need any instances of this type for the static member to be well-initialized.
Normally, people write member initialization in the constructor like this:
struct SomeType
{
int i;
SomeType()
{
i = 1;
}
}
But this is actually not initialization, but assignment. By the time you enter the body of the constructor, what you've done is default-initialize members. In the case of a fundamental type like an int, "default-initialization" basically boils down to "eh, just use whatever value was in those bytes I gave you."
What happens next is that you ask i to now adopt the value 1 via the assignment operator. For a trivial class like this, the difference is imperceptible. But when you have const members (which obviously cannot be tramped over with a new value by the time they are built), and more complex members which cannot be default-initialized (because they don't make available a visible constructor with zero parameters), you'll soon discover you cannot get the code to compile.
The correct way is:
struct SomeType
{
int i;
SomeType() : i(1)
{
}
}
This way you get members to be initialized rather than assigned to. You can initialize more than one by comma-separating them. One word of caution, they're initialized in the order of declaration inside your struct, not how you order them in this expression.
Sometimes you may see members initialized with braces (something like i{1} rather i(c)). The differences can be subtle, most of the time it's the same, and current revisions of the Standard are trying to smooth out some wrinkles. But that is all outside the scope of this question.
Update:
Bear in mind that what you're attempting to write is now valid C++ code, and has been since ratification of C++11. The feature is called "Non-static data member initializers", and I suspect you're using some version of Visual Studio, which still lists support as "Partial" for this particular feature. Think of it as a short-hand form of the member initialization syntax I described before, automatically inserted in any constructor you declare for this particular type.
You could make a default constructor
struct A {
A() : a{-1} {}
int a;
};
Forgive me my C++ is incredibly rusty. But I am trying to take some old code and recompile it under Visual C++ 2008. It was originally written for Visual C++ 6.0
The error I am getting is this:
error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
Ok seems simple enough. But then I look at the offending line of code:
operator=(int i) {SetAsInt(i);};
And it appears the type IS declared. So what am I missing?
FOLLOW UP:
I took Micheals advice and added a return type of the function (the class), and added return this; to the end of each. Then I ran across this:
operator=(const CString& str);
There is no function body defined... what exactly does this mean?
You need to have the operator=() method return something (it would assume int if the diagnostic weren't an error, as the error message somewhat confusingly indicates).
Generally it would be a reference to the object the operator is working on so the assignments can be chained as in a normal assignment expression. Something like:
// where T is the class for this operator= implementation
T& operator=( int i) {
// ...
return *this;
}
As michael has said, operator= needs a return type, but this type can be void:
class A {
...
void operator = ( int i ) {
SetAsInt(i);
}
};
although this means you won't be able to "daisy-chain" assignments.
Regarding the follow-up, it's probably saying that assignment for the class is forbidden:
class B {
private:
void operator =( const B & );
};
Making the assignment op (and usually the copy ctor) private and then not implementing them means it is impossible to assign (or copy) class instances, which is desirable behaviour for most business -oriented classes.
For your second question, the declaration is likey being used to prevent copying the object.
From the C++ Reference Guide by Danny Kalev
Question: How Can I Prevent
Object-Copying?
Answer: Declare the copy constructor
and the assignment operator as private
members, without defining them. Any
statement that involves direct or
indirect copying of that class will
cause a compilation error. This
technique isn’t exactly the picture of
elegance, but in contemporary C++
there’s no other way to block copying
inexpensively.
Regarding your edit:
It simply means that the function has been declared, but not defined. The compiler knows it exists, so it is legal to call it. But it will generate a linker error, unless the compiler is actually able to find the body somewhere.
Typically, you define the function in a header file, and then in the .cpp file, you have something like
// Assuming the class it is a member of is called Foo
Foo& Foo::operator=(const CString& str) {
...
}
The only thing to note here is the Foo:: prefix. Because this definition is outside the class definition itself, we have to use this prefix to specify that the operator= we're defining belongs to the Foo class.
returning ANYTHING but an lval is typically wrong and is only used in very special situations
certainly returning a const reference precludes assignment chaining (a=(b=c)), and part of the point of operators is to make classes behave like built in types
Well, that's an assignment operator. It helps one define how other objects (both of the same and other types) are assigned to an instance of the class it is defined within.
The correct syntax is (assuming your class is called 'Object'):
const Object& operator=(const Object& other)
{
// copy members, one at a time.
this->member1 = other.member1;
return *this;
}
Notice the return type is constant. This is a to avoid semantically incorrect, syntactically correct statements such as:
Object A, B, C;
(A = B) = C;
If you define the return type as constant, the above code will not compile (reasonable enough, since it's really messed up) while leaving out the const will allow such bad code to compile, and of course someone will pull their hair trying to figure out what's wrong.
P.S. You might want to think it through: what would happen if you leave out the const from the return type and execute the (A = B) = C; code?
Regarding the follow-up question, the return type can be anything in this case. However, since most assignment operators return a reference to the class in which they are declared, it would be best to return just that, in order not to confuse the reader.
CString& operator=(const CString& str);
Presumably, this function is declared in the private section of the class. This is the standard idiom to make objects of the class non-assignable.
Given a declaration like this:
class A {
public:
void Foo() const;
};
What does it mean?
Google turns up this:
Member functions should be declared with the const keyword after them if they can operate on a const (this) object. If the function is not declared const, in can not be applied to a const object, and the compiler will give an error message.
But I find that somewhat confusing; can anyone out there put it in better terms?
Thanks.
Consider a variation of your class A.
class A {
public:
void Foo() const;
void Moo();
private:
int m_nState; // Could add mutable keyword if desired
int GetState() const { return m_nState; }
void SetState(int val) { m_nState = val; }
};
const A *A1 = new A();
A *A2 = new A();
A1->Foo(); // OK
A2->Foo(); // OK
A1->Moo(); // Error - Not allowed to call non-const function on const object instance
A2->Moo(); // OK
The const keyword on a function declaration indicates to the compiler that the function is contractually obligated not to modify the state of A. Thus you are unable to call non-const functions within A::Foo nor change the value of member variables.
To illustrate, Foo() may not invoke A::SetState as it is declared non-const, A::GetState however is ok because it is explicitly declared const. The member m_nState may not be changed either unless declared with the keyword mutable.
One example of this usage of const is for 'getter' functions to obtain the value of member variables.
#1800 Information: I forgot about mutable!
The mutable keyword instructs the compiler to accept modifications to the member variable which would otherwise cause a compiler error. It is used when the function needs to modify state but the object is considered logically consistent (constant) regardless of the modification.
This is not an answer, just a side comment. It is highly recommended to declare variables and constants const as much as possible.
This communicates your intent to users of your class (even/especially yourself).
The compiler will keep you honest to those intentions. -- i.e., it's like compiler checked documentation.
By definition, this prevents state changes you weren't expecting and can, possibly, allow you to make reasonable assumptions while in your methods.
const has a funny way of propagating through your code. Thus, it's a really good idea to start using const as early and as often as possible. Deciding to start const-ifying your code late in the game can be painful (easy, but annoying).
If you're using a language with static, compile time checks it's a great idea to make as much use of them as possible... it's just another kind of testing really.
Functions with const qualifier are not allowed to modify any member variables. For example:
class A
{
int x;
mutable int y;
void f() const
{
x = 1; // error
y = 1; // ok because y is mutable
}
};
C++ objects can be declared to be const:
const A obj = new A();
When an object is const, the only member functions that can be called on that object are functions declared to be const. Making an object const can be interpreted as making the object readonly. A const object cannot be changed, i.e. no data members of the object can be changed. Declaring a member function const means that the function is not allowed to make any changes to the data members of the object.
Two suggested best practices from experience:
(1) Declare const functions whenever possible. At first, I found this to be just extra work, but then I started passing my objects to functions with signatures like f(const Object& o), and suddenly the compiler barfed on a line in f such as o.GetAValue(), because I hadn't marked GetAValue as a const function. This can surprise you especially when you subclass something and don't mark your version of the virtual methods as const - in that case the compile could fail on some function you've never heard of before that was written for the base class.
(2) Avoid mutable variables when it's practical. A tempting trap can be to allow read operations to alter state, such as if you're building a "smart" object that does lazy or asynchronous i/o operations. If you can manage this with only one small mutable variable (like a bool), then, in my experience, this makes sense. However, if you find yourself marking every member variable as mutable in order to keep some operations const, you're defeating the purpose of the const keyword. What can go wrong is that a function which thinks it's not altering your class (since it only calls const methods) my invoke a bug in your code, and it could take a lot of effort to even realize this bug is in your class, since the other coder (rightly) assumes your data is const because he or she is only calling const methods.
const has a funny way of propagating through your code. Thus, it's a really good idea to start using const as early and as often as possible. Deciding to start const-ifying your code late in the game can be painful (easy, but annoying).
Additionally, you will easily run into problems if methods that should be const aren't! This will creep through the code as well, and make it worse and worse.
that will cause the method to not be able to alter any member variables of the object