25.4 — Virtual destructors, virtual assignment, and overriding virtualization

This browser is no longer supported.

Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.

Copy constructors and copy assignment operators (C++)

  • 8 contributors

Starting in C++11, two kinds of assignment are supported in the language: copy assignment and move assignment . In this article "assignment" means copy assignment unless explicitly stated otherwise. For information about move assignment, see Move Constructors and Move Assignment Operators (C++) .

Both the assignment operation and the initialization operation cause objects to be copied.

Assignment : When one object's value is assigned to another object, the first object is copied to the second object. So, this code copies the value of b into a :

Initialization : Initialization occurs when you declare a new object, when you pass function arguments by value, or when you return by value from a function.

You can define the semantics of "copy" for objects of class type. For example, consider this code:

The preceding code could mean "copy the contents of FILE1.DAT to FILE2.DAT" or it could mean "ignore FILE2.DAT and make b a second handle to FILE1.DAT." You must attach appropriate copying semantics to each class, as follows:

Use an assignment operator operator= that returns a reference to the class type and takes one parameter that's passed by const reference—for example ClassName& operator=(const ClassName& x); .

Use the copy constructor.

If you don't declare a copy constructor, the compiler generates a member-wise copy constructor for you. Similarly, if you don't declare a copy assignment operator, the compiler generates a member-wise copy assignment operator for you. Declaring a copy constructor doesn't suppress the compiler-generated copy assignment operator, and vice-versa. If you implement either one, we recommend that you implement the other one, too. When you implement both, the meaning of the code is clear.

The copy constructor takes an argument of type ClassName& , where ClassName is the name of the class. For example:

Make the type of the copy constructor's argument const ClassName& whenever possible. This prevents the copy constructor from accidentally changing the copied object. It also lets you copy from const objects.

Compiler generated copy constructors

Compiler-generated copy constructors, like user-defined copy constructors, have a single argument of type "reference to class-name ." An exception is when all base classes and member classes have copy constructors declared as taking a single argument of type const class-name & . In such a case, the compiler-generated copy constructor's argument is also const .

When the argument type to the copy constructor isn't const , initialization by copying a const object generates an error. The reverse isn't true: If the argument is const , you can initialize by copying an object that's not const .

Compiler-generated assignment operators follow the same pattern for const . They take a single argument of type ClassName& unless the assignment operators in all base and member classes take arguments of type const ClassName& . In this case, the generated assignment operator for the class takes a const argument.

When virtual base classes are initialized by copy constructors, whether compiler-generated or user-defined, they're initialized only once: at the point when they are constructed.

The implications are similar to the copy constructor. When the argument type isn't const , assignment from a const object generates an error. The reverse isn't true: If a const value is assigned to a value that's not const , the assignment succeeds.

For more information about overloaded assignment operators, see Assignment .

Was this page helpful?

Additional resources

  • C++ Classes and Objects
  • C++ Polymorphism
  • C++ Inheritance
  • C++ Abstraction
  • C++ Encapsulation
  • C++ OOPs Interview Questions
  • C++ OOPs MCQ
  • C++ Interview Questions
  • C++ Function Overloading
  • C++ Programs
  • C++ Preprocessor
  • C++ Templates

Virtual Function in C++

A virtual function (also known as virtual methods) is a member function that is declared within a base class and is re-defined (overridden) by a derived class. When you refer to a derived class object using a pointer or a reference to the base class, you can call a virtual function for that object and execute the derived class’s version of the method.

  • Virtual functions ensure that the correct function is called for an object, regardless of the type of reference (or pointer) used for the function call.
  • They are mainly used to achieve Runtime polymorphism .
  • Functions are declared with a virtual keyword in a base class.
  • The resolving of a function call is done at runtime.

Rules for Virtual Functions

The rules for the virtual functions in C++ are as follows:

  • Virtual functions cannot be static.
  • A virtual function can be a friend function of another class.
  • Virtual functions should be accessed using a pointer or reference of base class type to achieve runtime polymorphism.
  • The prototype of virtual functions should be the same in the base as well as the derived class.
  • They are always defined in the base class and overridden in a derived class. It is not mandatory for the derived class to override (or re-define the virtual function), in that case, the base class version of the function is used.
  • A class may have a virtual destructor but it cannot have a virtual constructor.

Compile time (early binding) VS runtime (late binding) behavior of Virtual Functions

Consider the following simple program showing the runtime behavior of virtual functions.

Explanation: Runtime polymorphism is achieved only through a pointer (or reference) of the base class type. Also, a base class pointer can point to the objects of the base class as well as to the objects of the derived class. In the above code, the base class pointer ‘bptr’ contains the address of object ‘d’ of the derived class.

Late binding (Runtime) is done in accordance with the content of the pointer (i.e. location pointed to by pointer) and Early binding (Compile-time) is done according to the type of pointer since the print() function is declared with the virtual keyword so it will be bound at runtime (output is print derived class as the pointer is pointing to object of derived class) and show() is non-virtual so it will be bound during compile time (output is show base class as the pointer is of base type).

Note: If we have created a virtual function in the base class and it is being overridden in the derived class then we don’t need a virtual keyword in the derived class, functions are automatically considered virtual functions in the derived class.

Working of Virtual Functions (concept of VTABLE and VPTR)

As discussed here , if a class contains a virtual function then the compiler itself does two things.

  • If an object of that class is created then a virtual pointer (VPTR) is inserted as a data member of the class to point to the VTABLE of that class. For each new object created, a new virtual pointer is inserted as a data member of that class.
  • Irrespective of whether the object is created or not, the class contains as a member a static array of function pointers called VTABLE . Cells of this table store the address of each virtual function contained in that class.

Consider the example below:  

virtual pointer and virtual table

Explanation: Initially, we create a pointer of the type base class and initialize it with the address of the derived class object. When we create an object of the derived class, the compiler creates a pointer as a data member of the class containing the address of VTABLE of the derived class.

A similar concept of Late and Early Binding is used as in the above example. For the fun_1() function call, the base class version of the function is called, fun_2() is overridden in the derived class so the derived class version is called, fun_3() is not overridden in the derived class and is a virtual function so the base class version is called, similarly fun_4() is not overridden so base class version is called.

Note: fun_4(int) in the derived class is different from the virtual function fun_4() in the base class as prototypes of both functions are different.

Limitations of Virtual Functions

  • Slower: The function call takes slightly longer due to the virtual mechanism and makes it more difficult for the compiler to optimize because it does not know exactly which function is going to be called at compile time.
  • Difficult to Debug: In a complex system, virtual functions can make it a little more difficult to figure out where a function is being called from.

Similar Reads

  • cpp-inheritance
  • cpp-virtual

Please Login to comment...

  • Best Smartwatches in 2024: Top Picks for Every Need
  • Top Budgeting Apps in 2024
  • 10 Best Parental Control App in 2024
  • Top Language Learning Apps in 2024
  • GeeksforGeeks Practice - Leading Online Coding Platform

Improve your Coding Skills with Practice

 alt=

What kind of Experience do you want to share?

cppreference.com

The rule of three/five/zero.

(C++20)
(C++20)
(C++11)
(C++20)
(C++17)
(C++11)
(C++11)
General topics
(C++11)
-
-expression
block


/
(C++11)
(C++11)
(C++11)
(C++20)
(C++20)
(C++11)

expression
pointer
specifier

specifier (C++11)
specifier (C++11)
(C++11)

(C++11)
(C++11)
(C++11)
Rule of three Rule of five Rule of zero External links

[ edit ] Rule of three

If a class requires a user-defined destructor , a user-defined copy constructor , or a user-defined copy assignment operator , it almost certainly requires all three.

Because C++ copies and copy-assigns objects of user-defined types in various situations (passing/returning by value, manipulating a container, etc), these special member functions will be called, if accessible, and if they are not user-defined, they are implicitly-defined by the compiler.

The implicitly-defined special member functions should not be used if the class manages a resource whose handle does not destroy the resource themselves (raw pointer, POSIX file descriptor, etc), whose destructor does nothing and copy constructor/assignment operator only copies the value of the handle, without duplicating the underlying resource.

Classes that manage non-copyable resources through copyable handles may have to declare copy assignment and copy constructor private and not provide their definitions (until C++11) define copy assignment and copy constructor as = delete (since C++11) . This is another application of the rule of three: deleting one and leaving the other to be implicitly-defined typically incorrect.

[ edit ] Rule of five

Because the presence of a user-defined (include = default or = delete declared) destructor, copy-constructor, or copy-assignment operator prevents implicit definition of the move constructor and the move assignment operator , any class for which move semantics are desirable, has to declare all five special member functions:

Unlike Rule of Three, failing to provide move constructor and move assignment is usually not an error, but it will result in a loss of performance.

[ edit ] Rule of zero

Classes that have custom destructors, copy/move constructors or copy/move assignment operators should deal exclusively with ownership (which follows from the Single Responsibility Principle ). Other classes should not have custom destructors, copy/move constructors or copy/move assignment operators [1] .

This rule also appears in the C++ Core Guidelines as C.20: If you can avoid defining default operations, do .

When a base class is intended for polymorphic use, its destructor may have to be declared public and virtual . This blocks implicit moves (and deprecates implicit copies), and so the special member functions have to be defined as = default [2] .

However, this makes the class prone to slicing, which is why polymorphic classes often define copy as = delete (see C.67: A polymorphic class should suppress public copy/move in C++ Core Guidelines), which leads to the following generic wording for the Rule of Five:

[ edit ] External links

.
  • Recent changes
  • Offline version
  • What links here
  • Related changes
  • Upload file
  • Special pages
  • Printable version
  • Permanent link
  • Page information
  • In other languages
  • This page was last modified on 24 September 2024, at 16:24.
  • Privacy policy
  • About cppreference.com
  • Disclaimers

Powered by MediaWiki

  • Stack Overflow for Teams Where developers & technologists share private knowledge with coworkers
  • Advertising & Talent Reach devs & technologists worldwide about your product, service or employer brand
  • OverflowAI GenAI features for Teams
  • OverflowAPI Train & fine-tune LLMs
  • Labs The future of collective knowledge sharing
  • About the company Visit the blog

Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Get early access and see previews of new features.

Must a c++ interface obey the rule of five?

What is the correct way to declare instantiation methods when defining an interface class?

Abstract base classes are required to have a virtual destructor for obvious reasons. However, the following compilation warning is then given: "'InterfaceClass' defines a non-default destructor but does not define a copy constructor, a copy assignment operator, a move constructor or a move assignment operator", which is the 'rule of five'.

I understand why the 'rule of five' should be obeyed in general, but is it still applicable for an abstract base class or interface?

My implimentation is then:

Is this correct? Should these methods be = delete instead? Is there some way of declaring the destructor to be virtual pure whilst also somehow remaining default?

Even if I declare the destructor as: virtual ~InterfaceClass() = default; , if I do not explicitly default the other four then I will get the same compiler warning.

Tl;dr: What is the correct way to satisfy the 'rule of five' for an interface class as the user must define a virtual destructor.

Thanks for your time and help!

  • abstract-class
  • virtual-destructor
  • rule-of-three

user7119460's user avatar

  • 2 "the following compilation warning is then given" - by which compiler/version? –  Tony Delroy Commented Apr 22, 2018 at 2:00
  • clang 6.0 warns about a depreciated copy constructor. clang-tidy 6.0 static analyser gives the specific warning string above. g++ 4.2.1 does not seem to trigger a warning for this case. I am using mac os High Sierra 10.13.4 –  user7119460 Commented Apr 22, 2018 at 2:18
  • 10 A base class destructor should be either protected (preventing polymorphic delete) or public and virtual (making polymorphic delete safe). The protected and virtual combination you have is quite weird. –  Ben Voigt Commented Apr 22, 2018 at 2:44
  • Thanks for the tip. I'll update the example to reflect this. –  user7119460 Commented Apr 22, 2018 at 2:57
  • 2 Non-owning interfaces, that don't own, shouldn't own, that's the rule of zero. en.cppreference.com/w/cpp/language/rule_of_three –  Mikhail Commented Apr 22, 2018 at 7:44

4 Answers 4

Is this correct? Should these methods be = delete instead?

Your code seems correct. The need of defining special copy/move member functions as default and protected comes clear when you try to copy a derived class polymorphycally. Consider this additional code:

And consider 4 options for defining special copy/move member functions in your InterfaceClass.

  • copy/move member functions = delete

With special copy/move member functions deleted in your InterfaceClass, you would prevent polymorphic copy:

This is good, because polymorphic copy would not be able to copy the data member in the derived class.

On the other hand, you would also prevent normal copy, as the compiler won't be able to implicitly generate a copy assignment operator without the base class copy assignment operator:

  • copy/move special member functions public

With copy/move special member functions as default and public, (or without defining copy/move member functions), normal copy would work:

but polymorphic copy would be enabled and lead to slicing:

  • copy/move special member functions not defined

If move&copy special member functions are not defined, behavior with respect to copy is similar to 2: the compiler will implicitly generate deprecated copy special members (leading to polymorphic slicing). However in this case the compiler will not implicitly generate move special members, so copy will be used where a move would be possible.

  • protected copy/move member functions (your proposal)

With special copy/move member functions as default and protected, as in your example, you will prevent polymorphic copy which would otherwise had lead to slicing:

However, the compiler will explicitly generate a default copy assignment operator for InterfaceClass, and ImplementationClass will be able to implicitly generate its copy assignment operator:

So your approach seems the best and safest alternative

Gianni's user avatar

  • Regarding 1 and 4: On the other hand, you would also prevent normal copy, as the compiler won't be able to implicitly generate a copy assignment operator without the base class copy assignment operator (...) well why is that not good? To avoid the risk of slicing, follow C.67: A polymorphic class should suppress public copy/move . If you want to "clone" a polymorphic type add a clone function (C.130). The clone API can be supported by derived classes. –  Sonic78 Commented Oct 12, 2023 at 18:27

For destructor, if you want to make it both pure virtual and default, you can default it in implementation:

It does not make much difference if the destructor is default or empty, though.

Now for the rest of your question.

Typically you should have copy constructor and assignment operator defaulted. This way, they don't prevent making default assignment operators and copy constructor in derived classes. Default implementation is correct, as there's no invariant to copy.

So if you want to implement easily Clone method, deleting copy constructor would harm:

Note also that default implementation of copy/move constructor would not be accidentally used against intention - as instances of abstract base class cannot be created. So you will always be copying derived classes, and they should define, if copying is legal or not.

However, for some classes making copies totally would not make sense, in this case it may be wise to prohibit copying/assigning in the very base class.

Tl;dr: it depend, but most likely you'd better leave them as default.

Alex Guteniev's user avatar

In general, if any of the big 3 special functions has none-[trivial/default] definition, the other 2 should be defined. If the 2 special move functions have none-[trivial-default] definition, then you need take care of all 5. In the case of an interface with a nop defined dtor, you don't need bother defining the rest - unless for other reasons. Even none-trivial definitions do not nessecitate a redefinition of other functions; only when some sort of resource management(e.g. memory, file, io, sync...) is involved, one need define the big 3(5).

Red.Wave's user avatar

  • Only defining the big 3 is indeed safe, but move semantic special members will not be implicitly generated , and you will force objects to be copied when they could be moved. What does nop defined dtor mean? non-public? Does this solve the problem of slicing in polymorphic copy? I would happily do without defining special member functions in interfaces if I was sure it was safe –  Gianni Commented Mar 8, 2019 at 9:15
  • @Gianni nop means no-operation. Move is not always different or cheaper than copy. Move is just an optimization or a means of ownership transfer on none-copyable objects. –  Red.Wave Commented Mar 8, 2019 at 10:34

I ran into this problem recently in trying to define an abstract Observer class. Clang-tidy (version 14.0.6) gives a very similar warning to the original, marked [cppcoreguidelines-special-member-functions] . At first I tried to define copy/move constructors and copy/move assignment operators, marked = delete (also tried = default ). Eventually I got a compilation error because the concrete Observer did need a regular constructor to get a Subject pointer to register for notifications.

Upon reflection, however, I think no abstract class really needs a copy/move constructor (and therefore doesn't need to follow the rule of three/five), because by definition, an abstract class cannot be instantiated. So clang-tidy or any other compiler/analyzer that issues a "special member functions" warning on an abstract class is incorrect.

Joe Abbate's user avatar

Your Answer

Reminder: Answers generated by artificial intelligence tools are not allowed on Stack Overflow. Learn more

Sign up or log in

Post as a guest.

Required, but never shown

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy .

Not the answer you're looking for? Browse other questions tagged c++ abstract-class c++17 virtual-destructor rule-of-three or ask your own question .

  • The Overflow Blog
  • Masked self-attention: How LLMs learn relationships between tokens
  • Deedy Das: from coding at Meta, to search at Google, to investing with Anthropic
  • Featured on Meta
  • User activation: Learnings and opportunities
  • Preventing unauthorized automated access to the network
  • Feedback Requested: How do you use the tagged questions page?

Hot Network Questions

  • Estimating an upper bound of hyperbolicity constants in Gromov-hyperbolic groups
  • Matter made of neutral charges does not radiate?
  • How can I make second argument path relative to the first on a command?
  • Combining mean and covariance matrix of two populations
  • How can I make a 2D FTL-lane map on a galaxy-wide scale?
  • Purpose of sleeve on sledge hammer handle
  • Unbounded expansion in Tex
  • Book where the humans discover tachyon technology and use this against a race of liquid metal beings
  • God the Father punished the Son as sin-bearer: how does that prove God’s righteousness?
  • Is my TOTP key secure on a free hosting provider server with FTP and .htaccess restrictions?
  • How similar were the MC6800 and MOS 6502?
  • Does this work for page turns in a busy violin part?
  • Can I redeem myself with a better research paper if my thesis sucks?
  • Easily unload gravel from pickup truck
  • Is it possible to know where the Sun is just by looking at the Moon?
  • Does copying files from one drive to another also copy previously deleted data from the drive one?
  • Existence of antiderivative w.r.t. any given multi-index for tempered distributions
  • Will a car seat fit into a standard economy class seat on a plane?
  • Is a 1500w inverter suitable for a 10a portable band saw?
  • Why was Z moved to the end of the alphabet when Zeta was near the beginning?
  • How can I draw the intersection of a plane with a dome tent?
  • Do early termination fees hold up in court?
  • Why do evacuations result in so many injuries?
  • Why is my Lenovo ThinkPad running Ubuntu using the e1000e Ethernet driver?

cpp virtual assignment operator

IMAGES

  1. what is assignment operator

    cpp virtual assignment operator

  2. [Solved] virtual assignment operator C++

    cpp virtual assignment operator

  3. GitHub

    cpp virtual assignment operator

  4. GitHub

    cpp virtual assignment operator

  5. C++ Assignment Operator and Statement

    cpp virtual assignment operator

  6. Assignment Operator Overloading in C++

    cpp virtual assignment operator

VIDEO

  1. 6. Access Operator in C++

  2. QECI-CPP Partial Viewpoint Virtual Simulation Results Display

  3. C++ Operators

  4. CS231: Variables and Operators in C++

  5. C++ Virtual Functions Explained in 1 Minute!

  6. C++ Assignment Operators Practice coding

COMMENTS

  1. virtual assignment operator C++

    The assignment operator is not required to be made virtual. The discussion below is about operator=, but it also applies to any operator overloading that takes in the type in question, and any function that takes in the type in question.. The below discussion shows that the virtual keyword does not know about a parameter's inheritance in regards to finding a matching function signature.

  2. c++

    1. Virtual assignment is an ungood idea because it introduces run time type-checking, moving bug detection etc. to run-time with more extensive and unreliable testing. - Cheers and hth. - Alf. Jul 15, 2015 at 7:25. I you want to see Calling B message you should try this virtual B& operator=(const A& b_) override { std::cout << "Calling B ...

  3. Assignment operators

    Correct behavior. CWG 1527. C++11. for assignments to class type objects, the right operand could be an initializer list only when the assignment is defined by a user-defined assignment operator. removed user-defined assignment constraint. CWG 1538. C++11. E1 ={E2} was equivalent to E1 = T(E2) (T is the type of E1), this introduced a C-style cast.

  4. 25.4

    Virtual assignment It is possible to make the assignment operator virtual. However, unlike the destructor case where virtualization is always a good idea, virtualizing the assignment operator really opens up a bag full of worms and gets into some advanced topics outside of the scope of this tutorial.

  5. operator overloading

    When an operator appears in an expression, and at least one of its operands has a class type or an enumeration type, then overload resolution is used to determine the user-defined function to be called among all the functions whose signatures match the following: Expression. As member function. As non-member function.

  6. Copy assignment operator

    Triviality of eligible copy assignment operators determines whether the class is a trivially copyable type. [] NoteIf both copy and move assignment operators are provided, overload resolution selects the move assignment if the argument is an rvalue (either a prvalue such as a nameless temporary or an xvalue such as the result of std::move), and selects the copy assignment if the argument is an ...

  7. Copy constructors and copy assignment operators (C++)

    Use an assignment operator operator= that returns a reference to the class type and takes one parameter that's passed by const reference—for example ClassName& operator=(const ClassName& x);. Use the copy constructor. If you don't declare a copy constructor, the compiler generates a member-wise copy constructor for you.

  8. Assignment Operators In C++

    In C++, the multiplication assignment operator (*=) is used to update the value of the variable by multiplying it with another value. Syntax. variable *= value; This above expression is equivalent to the expression: variable = variable * value; Example. C++. #include <iostream>. using namespace std;

  9. My textbook says that virtual assignment operator overloading ...

    It is possible to make the assignment operator virtual. However, unlike the destructor case where virtualization is always a good idea, virtualizing the assignment operator really opens up a bag full of worms and gets into some advanced topics outside of the scope of this tutorial. ... Thank you r/cpp_questions for not being like that! And that ...

  10. Copy Constructor vs Assignment Operator in C++

    It is a bitwise operator. C++ compiler implicitly provides a copy constructor, if no copy constructor is defined in the class. A bitwise copy gets created, if the Assignment operator is not overloaded. Syntax: className (const className &obj) {. // body. } Syntax: className obj1, obj2;

  11. Taligent's Guide to Designing Programs

    When to use virtual assignment. Assignment, or operator=, is a function that requires careful consideration before you make it virtual. You might think that, like other members, it is better to make it virtual to be safe. Otherwise, you run into problems like this: void Bar (TFoo &arg) { arg = value; } If TFoo::operator= is not virtual, this ...

  12. virtual function specifier

    Moreover, if the destructor of the base class is not virtual, deleting a derived class object through a pointer to the base class is undefined behavior regardless of whether there are resources that would be leaked if the derived destructor is not invoked, unless the selected deallocation function is a destroying operator delete (since C++20).. A useful guideline is that the destructor of any ...

  13. C++ Assignment Operator Overloading

    Overloading assignment operator in C++ copies all values of one object to another object. Only a non-static member function should be used to overload the assignment operator. In C++, the compiler automatically provides a default assignment operator for classes. This operator performs a shallow copy of each member of the class from one object ...

  14. Move assignment operator

    The move assignment operator is called whenever it is selected by overload resolution, e.g. when an object appears on the left-hand side of an assignment expression, where the right-hand side is an rvalue of the same or implicitly convertible type.. Move assignment operators typically transfer the resources held by the argument (e.g. pointers to dynamically-allocated objects, file descriptors ...

  15. Move Assignment Operator in C++ 11

    The move assignment operator was added in C++ 11 to further strengthen the move semantics in C++. It is like a copy assignment operator but instead of copying the data, this moves the ownership of the given data to the destination object without making any additional copies. The source object is left in a valid but unspecified state.

  16. Help with virtual assignment operator : r/cpp_questions

    Posted by u/Koalchemy - 2 votes and 10 comments

  17. Virtual Function in C++

    Got it. A virtual function (also known as virtual methods) is a member function that is declared within a base class and is re-defined (overridden) by a derived class. When you refer to a derived class object using a pointer or a reference to the base class, you can call a virtual function for that object and execute the derived class's ...

  18. The rule of three/five/zero

    Rule of three. If a class requires a user-defined destructor, a user-defined copy constructor, or a user-defined copy assignment operator, it almost certainly requires all three.. Because C++ copies and copy-assigns objects of user-defined types in various situations (passing/returning by value, manipulating a container, etc), these special member functions will be called, if accessible, and ...

  19. Must a c++ interface obey the rule of five?

    Abstract base classes are required to have a virtual destructor for obvious reasons. However, the following compilation warning is then given: "'InterfaceClass' defines a non-default destructor but does not define a copy constructor, a copy assignment operator, a move constructor or a move assignment operator", which is the 'rule of five'.