@@ -1224,13 +1224,50 @@ void printCallStack()
1224
1224
class PureVirtualImplementedOtherBase
1225
1225
{
1226
1226
public:
1227
-
1228
- void pureVirtualImplementedOtherBase ()
1227
+ void pureVirtual ()
1228
+ {
1229
+ callStack.push_back (" PureVirtualImplementedOtherBase::pureVirtual()" );
1230
+ }
1231
+ private:
1232
+ void privatePureVirtual ()
1229
1233
{
1230
- callStack.push_back (" PureVirtualImplementedOtherBase::pureVirtualOtherBase ()" );
1234
+ callStack.push_back (" PureVirtualImplementedOtherBase::privatePureVirtual ()" );
1231
1235
}
1232
1236
};
1233
1237
1238
+ class DerivedAbtractAndImplementator : BaseAbstract, PureVirtualImplementedOtherBase
1239
+ {
1240
+ // public:
1241
+ // void pureVirtual()
1242
+ // {
1243
+ // callStack.push_back("PureVirtualImplementedOtherBase::pureVirtual()");
1244
+ // }
1245
+ // private:
1246
+ // void privatePureVirtual()
1247
+ // {
1248
+ // callStack.push_back("PureVirtualImplementedOtherBase::privatePureVirtual()");
1249
+ // }
1250
+ };
1251
+
1252
+ class MultipleInheritanceConflictBase1 {
1253
+ public:
1254
+ const static int is = 1 ;
1255
+ int i;
1256
+ void f (){}
1257
+ };
1258
+
1259
+ class MultipleInheritanceConflictBase2 {
1260
+ public:
1261
+ const static int is = 2 ;
1262
+ int i;
1263
+ void f (){}
1264
+ };
1265
+
1266
+ class MultipleInheritanceConflictDerived :
1267
+ MultipleInheritanceConflictBase1,
1268
+ MultipleInheritanceConflictBase2
1269
+ {};
1270
+
1234
1271
class BaseProtected
1235
1272
{
1236
1273
public:
@@ -1258,8 +1295,7 @@ void printCallStack()
1258
1295
// public Derived, //WARN cannot use BasePrivate inside: ambiguous
1259
1296
protected BaseProtected,
1260
1297
private BasePrivate,
1261
- public BaseAbstract,
1262
- public PureVirtualImplementedOtherBase
1298
+ public BaseAbstract
1263
1299
{
1264
1300
public:
1265
1301
@@ -6038,163 +6074,197 @@ int main(int argc, char **argv)
6038
6074
}
6039
6075
}
6040
6076
6041
- // #overridding
6077
+ /*
6078
+ #inheritance
6079
+ */
6042
6080
{
6043
- Class c;
6044
- Class* cp = &c;
6081
+ // #overridding
6082
+ {
6083
+ Class c;
6084
+ Class* cp = &c;
6045
6085
6046
- c.i = 0 ;
6047
- c.Class ::i = 0 ;
6048
- cp->Class ::i = 0 ;
6049
- c.Base ::i = 1 ;
6050
- c.BaseAbstract ::i = 2 ;
6086
+ c.i = 0 ;
6087
+ c.Class ::i = 0 ;
6088
+ cp->Class ::i = 0 ;
6089
+ c.Base ::i = 1 ;
6090
+ c.BaseAbstract ::i = 2 ;
6051
6091
6052
- assert (c.i == 0 );
6053
- assert (c.Class ::i == 0 );
6054
- assert (cp->Class ::i == 0 );
6092
+ assert (c.i == 0 );
6093
+ assert (c.Class ::i == 0 );
6094
+ assert (cp->Class ::i == 0 );
6055
6095
6056
- assert (c.Base ::i == 1 );
6057
- assert (cp->Base ::i == 1 );
6096
+ assert (c.Base ::i == 1 );
6097
+ assert (cp->Base ::i == 1 );
6058
6098
6059
- assert (c.BaseAbstract ::i == 2 );
6060
- assert (cp->BaseAbstract ::i == 2 );
6099
+ assert (c.BaseAbstract ::i == 2 );
6100
+ assert (cp->BaseAbstract ::i == 2 );
6061
6101
6062
- // c.iAmbiguous = 0;
6063
- // ERROR ambiguous
6064
- c.Base ::iAmbiguous = 0 ;
6065
- c.BaseAbstract ::iAmbiguous = 0 ;
6102
+ // c.iAmbiguous = 0;
6103
+ // ERROR ambiguous
6104
+ c.Base ::iAmbiguous = 0 ;
6105
+ c.BaseAbstract ::iAmbiguous = 0 ;
6066
6106
6067
- callStack.clear ();
6068
- c.method ();
6069
- assert (callStack.back () == " Class::method()" );
6070
- // c.methodAmbiguous();
6071
- // ERROR ambiguous
6072
- callStack.clear ();
6073
- c.Base ::methodAmbiguous ();
6074
- assert (callStack.back () == " Base::methodAmbiguous()" );
6107
+ callStack.clear ();
6108
+ c.method ();
6109
+ assert (callStack.back () == " Class::method()" );
6110
+ // c.methodAmbiguous();
6111
+ // ERROR ambiguous
6112
+ callStack.clear ();
6113
+ c.Base ::methodAmbiguous ();
6114
+ assert (callStack.back () == " Base::methodAmbiguous()" );
6075
6115
6076
- callStack.clear ();
6077
- c.BaseAbstract ::methodAmbiguous ();
6078
- assert (callStack.back () == " BaseAbstract::methodAmbiguous()" );
6116
+ callStack.clear ();
6117
+ c.BaseAbstract ::methodAmbiguous ();
6118
+ assert (callStack.back () == " BaseAbstract::methodAmbiguous()" );
6119
+ }
6079
6120
6080
6121
/*
6081
- #virtual inheritance
6122
+ #virtual
6082
6123
6083
- <http://en.wikipedia.org/wiki/Virtual_inheritance>
6124
+ Virtual: decides on runtime based on object type.
6084
6125
6085
- TODO
6086
- */
6087
- }
6126
+ <http://stackoverflow.com/questions/2391679/can-someone-explain-c-virtual-methods>
6088
6127
6089
- /*
6090
- #virtual
6128
+ #pure virtual function
6129
+
6130
+ Cannot instantiate this class
6131
+
6132
+ Can only instantiate derived classes that implement this.
6133
+
6134
+ If a class has a pure virtual method is called as an *abstract class* or *interface*.
6135
+
6136
+ In Java there is a language difference between those two terms,
6137
+ and it might be a good idea to differentiate them when speaking about C++:
6091
6138
6092
- Virtual: decides on runtime based on object type.
6139
+ - interface: no data
6140
+ - abstract: data
6093
6141
6094
- <http://stackoverflow.com/questions/2391679/can-someone-explain-c-virtual-methods>
6142
+ #polymorphism
6095
6143
6096
- #pure virtual function
6144
+ - loop an array of several dereived classes
6145
+ - call a single base class method
6146
+ - uses the correct derived override
6097
6147
6098
- Cannot instantiate this class
6148
+ Implementation: *vtable* is used to implement this.
6099
6149
6100
- Can only instantiate derived classes that implement this.
6150
+ #vtable
6101
6151
6102
- If a class has a pure virtual method is called as an *abstract class* or *interface*.
6152
+ <http://en.wikipedia.org/wiki/Virtual_method_table>
6103
6153
6104
- In Java there is a language difference between those two terms,
6105
- and it might be a good idea to differentiate them when speaking about C++:
6154
+ Whenever you create a pointer to a class with a virtual method,
6155
+ that pointer points to a pointer that identifies the class type,
6156
+ and points to the correct method.
6106
6157
6107
- - interface: no data
6108
- - abstract: data
6158
+ Consequence: every call to a virtual methods means:
6109
6159
6110
- #polymorphism
6160
+ - an extra pointer dereference
6161
+ - an extra pointer stored in memory
6111
6162
6112
- - loop an array of several dereived classes
6113
- - call a single base class method
6114
- - uses the correct derived override
6163
+ Also virtual functions cannot be inlined.
6115
6164
6116
- Implementation: *vtable* is used to implement this.
6165
+ #Static interfaces
6117
6166
6118
- # vtable
6167
+ It is possible to assert that interfaces are implemented without dynamic vtable overhead via CRTP:
6119
6168
6120
- <http://en.wikipedia.org/wiki/Virtual_method_table >
6169
+ - <http://stackoverflow.com/questions/2587541/does-c-have-a-static-polymorphism-implementation-of-interface-that-does-not-us >
6121
6170
6122
- Whenever you create a pointer to a class with a virtual method,
6123
- that pointer points to a pointer that identifies the class type,
6124
- and points to the correct method.
6171
+ - <http://en.wikipedia.org/wiki/Template_metaprogramming#Static_polymorphism>
6125
6172
6126
- Consequence: every call to a virtual methods means:
6173
+ #CRTP
6127
6174
6128
- - an extra pointer dereference
6129
- - an extra pointer stored in memory
6175
+ Curiously recurring template pattern.
6130
6176
6131
- Also virtual functions cannot be inlined.
6177
+ <http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern#Static_polymorphism>
6178
+ */
6179
+ {
6180
+ // BaseAbstract b;
6181
+ // ERROR: BaseAbstract cannot be instantiated because it contains a pure virtual method
6182
+ // virtual = 0;. That method must be implemented on derived classes
6132
6183
6133
- #Static interfaces
6184
+ // even if you can't instantiate base, you can have pointers to it
6185
+ {
6186
+ BaseAbstract* bap = new Class;
6187
+ // BaseAbstract* bap = &c;
6188
+ // SAME
6134
6189
6135
- It is possible to assert that interfaces are implemented without dynamic vtable overhead via CRTP:
6190
+ callStack.clear ();
6191
+ bap->method ();
6192
+ assert (callStack.back () == " BaseAbstract::method()" );
6193
+ // base method because non-virtual
6136
6194
6137
- - <http://stackoverflow.com/questions/2587541/does-c-have-a-static-polymorphism-implementation-of-interface-that-does-not-us>
6195
+ callStack.clear ();
6196
+ bap->virtualMethod ();
6197
+ assert (callStack.back () == " Class::virtualMethod()" );
6198
+ // class method because virtual
6138
6199
6139
- - <http://en.wikipedia.org/wiki/Template_metaprogramming#Static_polymorphism>
6200
+ delete bap;
6201
+ }
6140
6202
6141
- #CRTP
6203
+ {
6204
+ // you can also have BaseAbstract&
6205
+ Class c;
6206
+ BaseAbstract& ba = c;
6142
6207
6143
- Curiously recurring template pattern.
6208
+ callStack.clear ();
6209
+ ba.method ();
6210
+ assert (callStack.back () == " BaseAbstract::method()" );
6144
6211
6145
- <http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern#Static_polymorphism>
6146
- */
6147
- {
6148
- // BaseAbstract b;
6149
- // ERROR: BaseAbstract cannot be instantiated because it contains a pure virtual method
6150
- // virtual = 0;. That method must be implemented on derived classes
6212
+ callStack.clear ();
6213
+ ba.virtualMethod ();
6214
+ assert (callStack.back () == " Class::virtualMethod()" );
6215
+ }
6151
6216
6152
- // even if you can't instantiate base, you can have pointers to it
6153
- {
6154
- BaseAbstract* bap = new Class;
6155
- // BaseAbstract* bap = &c;
6156
- // SAME
6217
+ {
6218
+ Class c = Class ();
6219
+ Base* bp = &c;
6220
+ bp = bp->covariantReturn ();
6157
6221
6158
- callStack.clear ();
6159
- bap->method ();
6160
- assert (callStack.back () == " BaseAbstract::method()" );
6161
- // base method because non-virtual
6222
+ callStack.clear ();
6223
+ bp->virtualMethod ();
6224
+ assert (callStack.back () == " Class::virtualMethod()" );
6162
6225
6163
- callStack. clear ();
6164
- bap-> virtualMethod ();
6165
- assert (callStack. back () == " Class::virtualMethod() " );
6166
- // class method because virtual
6226
+ // classPtr = basePtr->covariantReturn ();
6227
+ // ERROR
6228
+ // conversion from Base to Class
6229
+ }
6167
6230
6168
- delete bap;
6231
+ /*
6232
+ It is not possibleto implement pure virtual methods on another base class:
6233
+ they must be implemented on the Derived class.
6234
+ */
6235
+ {
6236
+ // DerivedAbtractAndImplementator d; //ERROR
6237
+ }
6169
6238
}
6170
6239
6171
- {
6172
- // you can also have BaseAbstract&
6173
- Class c;
6174
- BaseAbstract& ba = c;
6240
+ /*
6241
+ #multiple inheritance
6175
6242
6176
- callStack. clear ();
6177
- ba. method ();
6178
- assert (callStack. back () == " BaseAbstract::method() " );
6243
+ In C++, if a member of an object or static variable of a class
6244
+ comes from two base classes, an ambiguity occurs and the program does not
6245
+ compile.
6179
6246
6180
- callStack.clear ();
6181
- ba.virtualMethod ();
6182
- assert (callStack.back () == " Class::virtualMethod()" );
6247
+ This just makes multiple inheritance very insane, since the addition of
6248
+ new fields in a Base class can break existing code on Derived classes.
6249
+ */
6250
+ {
6251
+ // MultipleInheritanceConflictDerived::is;
6252
+ // MultipleInheritanceConflictDerived().i;
6253
+ // MultipleInheritanceConflictDerived().f();
6183
6254
}
6184
6255
6185
- {
6186
- Class c = Class ();
6187
- Base* bp = &c;
6188
- bp = bp->covariantReturn ();
6256
+ /*
6257
+ #dreaded diamond
6189
6258
6190
- callStack.clear ();
6191
- bp->virtualMethod ();
6192
- assert (callStack.back () == " Class::virtualMethod()" );
6259
+ #virtual inheritance
6193
6260
6194
- // classPtr = basePtr->covariantReturn();
6195
- // ERROR
6196
- // conversion from Base to Class
6197
- }
6261
+ Solves the dreaded diamond problem.
6262
+
6263
+ Has nothing to do with the `virtual` keyword for methods:
6264
+ everything is done at compile time in thie usage.
6265
+
6266
+ <http://stackoverflow.com/questions/21558/in-c-what-is-a-virtual-base-class>
6267
+ */
6198
6268
}
6199
6269
6200
6270
// #friend
0 commit comments