4

For example is this correct:

class C 
{
   private: 
     C();
     C(const & C other);
}

or you should rather provide definition(s):

class C 
{
   private: 
     C() {};
     C(const & C other) {};
}

? Thanks for the current answers. Let's extend this question - does compiler generate better code in one of this examples? I can imagine that providing body for ctor forces compiler to include some (empty) code in compilation unit? Is this also true for auto-generated code?

mip
  • 8,355
  • 6
  • 53
  • 72

8 Answers8

11

If you do not wish your object to be copyable, then there is no need to provide the implementation. Just declare the copy ctor private without any implementation. The same holds for other ctors, if you do not want any body to use them, just declare them private without any implementation.

Naveen
  • 74,600
  • 47
  • 176
  • 233
9

It is fine as long as you don't use them.

With the 0x standard you can use deleted functions.

class X {
   // ...
   X& operator=(const X&) = delete; // Disallow copying
   X(const X&) = delete;
};
Fernando N.
  • 6,369
  • 4
  • 27
  • 30
  • Thanks I would like to accept your answer as well but it's not possible and Naveen was first. – mip Nov 13 '09 at 12:33
5

You may use declaration-only constructors to disallow given constructions, like standard construction, or copy-construction.

For example, if you want to avoid your object being copied you can declare as private the copy-constructor and the assignment operator and do not define them, then anyone,including you, who tries to copy the object will have linker errors.

About your last edit: I'd expect a decent compiler to produce the same code for a default constructor and for an empty constructor and no initialization list, in the end, what it needs to do is default-initialize each member.

Arkaitz Jimenez
  • 22,500
  • 11
  • 75
  • 105
  • I mean linker errors, all your objects will compile and when they try to link they'll find that constructor(const&obj) symbol is missing, so linker error. – Arkaitz Jimenez Nov 13 '09 at 12:12
  • When constructor is declared private it won't compile, unless you are using singleton. – mip Nov 13 '09 at 12:18
  • Wrong, it will compile if you call it from the inside, it doesn't need to be a singleton, you may have several static methods that produce one or more objects of your class with a private constructor. – Arkaitz Jimenez Nov 13 '09 at 12:19
  • Assume they are not intended to be called from inside the class. In such case my question would be a nonsense. – mip Nov 13 '09 at 12:24
  • If they are intended to be called **and** you have declared them at all then you need to define them, you can't declare them and expect the compiler to generate a default constructor, it won't. – Arkaitz Jimenez Nov 13 '09 at 12:28
  • They are NOT intended to be called. – mip Nov 13 '09 at 12:30
  • Then just declare them as private. – Arkaitz Jimenez Nov 13 '09 at 12:31
  • And in this example are they declared public? – mip Nov 13 '09 at 12:34
  • I'm not saying they are, you just wrongly corrected me about the errors and the thread lead to this, I didn't say anything incorrect. – Arkaitz Jimenez Nov 13 '09 at 12:35
  • If they are declared as private, then you won't get linker errors because compiler will trigger errors first. The only case when this could compile is when calling them from inside the class. But then my example makes no sense, so it is obvious to assume that they are not intended to be called from inside the class. – mip Nov 13 '09 at 12:49
2

If you declare them without providing implementation, then you can't use them because they don't exist. If you want to use the constructors, you must either allow the compiler to create them by not declaring them, OR you must declare them and provide an implementation.

It is occasionally useful to provide a declaration but no implementation for a constructor that you don't want used. This is often done with the copy constructor for objects (such as singletons) that you don't want there to be copies of, ever. In such cases, the declaration is often made private as well.

Michael Kohne
  • 11,888
  • 3
  • 47
  • 79
2

Firstly, if you want to make your class completely non-copyable, don't implement the private copy constructor and assignment operator. Otherwise it is still possible that a piece of code that has access (a method or a friend) can silently make copies. Without the implementation, you'll get a linker error.

However, a compiler error would be preferable, as you'll find out about the error faster. For this there's boost::noncopyable, or you can derive from a base class that hides its copy constructor and assignment operator.

Concerning the default constructor: the compiler will not generate one if you declare any constructor at all. There's generally no need to hide that specifically.

UncleBens
  • 40,819
  • 6
  • 57
  • 90
  • Thanks, this is really nice answer. So far I was using Java a lot, learning many OOP concepts with her, and probably she impressed a stamp on mind XP – mip Nov 14 '09 at 07:30
0

If you use the 'empty' declaration, the compiler will no longer generate the default implementation and you will get link errors. If you declare them, you have to write them so the empty-brace form is necessary.

Jeff Paquette
  • 7,089
  • 2
  • 31
  • 40
0

You will need to provide definitions. If you do not, and you attempt to use them, it will fail to link.

Alex Deem
  • 4,717
  • 1
  • 21
  • 24
  • Note that this constructors are private and assume that they won't be used by class itself. – mip Nov 13 '09 at 12:08
  • I consider this to be a feature. If I do not wish anyone to make a copy -- either clients of my class or even myself -- then I want the compiler to tell me off when I try to do so. – Kaz Dragon Nov 13 '09 at 12:14
  • 1
    Ignore me, I failed to realise they were private... :) – Alex Deem Nov 13 '09 at 12:30
0

That depends on whether you use these constructors or not. If you don't use them you may leave them undefined. If you use them (for example you are creating objects of the class from static functions of class, you need to define them) you need to provide definitions, otherwise you'll get unresolved external symbols error from linker.

Paul
  • 13,042
  • 3
  • 41
  • 59