Forum Replies Created
-
AuthorPosts
-
::
Friendship should only be granted exclusively. The following rules hold:
class A { friend class B; }; class B { friend class C; }; class C {}; // 1. friendship is not transitive class D : B {} // 2. friendship is not inherited
- Friendship is not transitive: class B is a friend of class A, and class C is a friend of class B ⇒ class C is not a friend of class C
- Friendship is not inherited: class B is a friend of class A, and class D derives from class B ⇒ class D is not a friend of class A
The same rules apply to functions. ⇒ Friendship is not inherited.
::This is mainly a matter of taste of how you structure source code. There are a few subtle differences:
- When you define a member function inside the class, it becomes automatically inline.
- The syntax becomes pretty complicated when you define a generic member function outside a class template. The member function has to specify the class template declaration and the member function declaration.
template <typename T, int N> class Array{ public: template <typename T2> Array<T, N>& operator = (const Array<T2, N>& a); }; template <typename T, int N> template <typename T2> Array<T, N>& Array<T, N>::operator = (const Array<T2, N>& a) { }
- When a template is instantiated, its definition must be available. Consequentially, you have to include the member function definition in the header.
// foo.h template <typename T> struct Foo{ void func(T param); }; #include "foo.cpp"
::- Deriving publicly means that the derived class is a base class. Therefore, you can use the derived class in a function call when a base class is required. The derived class is a base class.
- Deriving privately means that the derived class can only use public and protected members of the base class. The derived class uses the base class for its implementation.
::struct MyType{};- Copy constructor and move constructor
MyType my1; MyType my2(my1); // copy constructor MyType my3(std::move(my1)); // move constructor
Steps of copy and move constructor:
- Create yourself from the other
- Special step
- Move Constructor: put the other in a valid but unspecified state
- Copy assignment operator and move assignment operator
MyType my1; MyType my2; m1 = m2; // copy assignment operator m1 = std::move(m2); // move assignment operatorSteps of copy assignment and move assignment operator
- Delete yourself
- Initialize yourself from the other
- Special step
- Copy assignment operator: check for self assignment
- Move assignment operator: put the other in a valid but unspecified state
::Just put the Account‘s in an additional scope in main. Now, you see the expected behavior: https://godbolt.org/z/PYajYv14o
::This is a topic of my Design Pattern mentoring, but you can read the following post in which I compare the various techniques: https://www.modernescpp.com/index.php/c-core-guidelines-more-about-control-structures.
::Here is an idea for a class having a constexpr and non-constexpr constructor
- Instances of your class should be creatable at compile time. => You make your constructors constexpr. Consequentially, you can use this constructor also at run time.
- Now, you need a constructor that performs some operations, which are only doable at run time. E.g.: invoke a logger. A logger cannot be constexpr because it logs the time. => You have a class with constexpr and non-constexpr constructors.
::- It behaves such as the compiler first creates a representation of the class before it uses it. For the same reason it works that you can invoke a member function before it was declared: https://godbolt.org/z/h9djnP9oa
- In the concrete case, initialization in the class body and the constructor is the same. In general, in class initialization is the default behavior of a class and constructor initialization is a special initialization.
-
AuthorPosts
