mirror of
https://github.com/cirosantilli/linux-kernel-module-cheat.git
synced 2026-01-23 02:05:57 +01:00
virtual.cpp
This commit is contained in:
@@ -17265,6 +17265,8 @@ Programs under link:userland/cpp/[] are examples of https://en.wikipedia.org/wik
|
|||||||
*** link:userland/cpp/most_vexing_parse.cpp[]: the most vexing parse is a famous constructor vs function declaration syntax gotcha!
|
*** link:userland/cpp/most_vexing_parse.cpp[]: the most vexing parse is a famous constructor vs function declaration syntax gotcha!
|
||||||
**** https://en.wikipedia.org/wiki/Most_vexing_parse
|
**** https://en.wikipedia.org/wiki/Most_vexing_parse
|
||||||
**** http://stackoverflow.com/questions/180172/default-constructor-with-empty-brackets
|
**** http://stackoverflow.com/questions/180172/default-constructor-with-empty-brackets
|
||||||
|
** `virtual` and polymorphism
|
||||||
|
*** link:userland/cpp/virtual.cpp[]
|
||||||
* templates
|
* templates
|
||||||
** link:userland/cpp/template.cpp[]: basic example
|
** link:userland/cpp/template.cpp[]: basic example
|
||||||
** link:userland/cpp/template_class_with_static_member.cpp[]: https://stackoverflow.com/questions/3229883/static-member-initialization-in-a-class-template
|
** link:userland/cpp/template_class_with_static_member.cpp[]: https://stackoverflow.com/questions/3229883/static-member-initialization-in-a-class-template
|
||||||
@@ -19019,7 +19021,7 @@ Examples:
|
|||||||
|
|
||||||
* link:userland/linux/sched_getcpu.c[]
|
* link:userland/linux/sched_getcpu.c[]
|
||||||
* link:userland/linux/getcpu.c[]: a wrapper close the the syscall that also returns the current NUMA node
|
* link:userland/linux/getcpu.c[]: a wrapper close the the syscall that also returns the current NUMA node
|
||||||
* link:userland/linux/getcpu_syscal.c[]: the wrapper segfaults on error handling, so double checking with the real syscall: https://stackoverflow.com/questions/9260937/unix-socket-error-14-efault-bad-address/61879849#61879849
|
* link:userland/linux/getcpu_syscall.c[]: the wrapper segfaults on error handling, so double checking with the real syscall: https://stackoverflow.com/questions/9260937/unix-socket-error-14-efault-bad-address/61879849#61879849
|
||||||
* link:userland/linux/sched_getcpu_barrier.c[]: this uses a barrier to ensure that gem5 will run each thread on one separate CPU
|
* link:userland/linux/sched_getcpu_barrier.c[]: this uses a barrier to ensure that gem5 will run each thread on one separate CPU
|
||||||
|
|
||||||
Returns the CPU that the process/thread is currently running on:
|
Returns the CPU that the process/thread is currently running on:
|
||||||
|
|||||||
116
userland/cpp/virtual.cpp
Normal file
116
userland/cpp/virtual.cpp
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
// https://cirosantilli.com/linux-kernel-module-cheat#cpp
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
|
||||||
|
// Hello world.
|
||||||
|
{
|
||||||
|
struct Base {
|
||||||
|
virtual int f() { return 0; }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Derived1 : public Base {
|
||||||
|
virtual int f() override { return 1; }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Derived2 : public Base {
|
||||||
|
// virtual not required on the last derived method.
|
||||||
|
int f() override { return 2; }
|
||||||
|
};
|
||||||
|
|
||||||
|
// Depending on what bp actually points to, we call different functions.
|
||||||
|
// This is what is called polymorphism.
|
||||||
|
|
||||||
|
Base *bp;
|
||||||
|
|
||||||
|
Base b;
|
||||||
|
bp = &b;
|
||||||
|
assert(bp->f() == 0);
|
||||||
|
|
||||||
|
Derived1 d1;
|
||||||
|
bp = &d1;
|
||||||
|
assert(bp->f() == 1);
|
||||||
|
|
||||||
|
Derived2 d2;
|
||||||
|
bp = &d2;
|
||||||
|
assert(bp->f() == 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Without `virtual`, no polymorphism happens!
|
||||||
|
// We get name hiding instead.
|
||||||
|
{
|
||||||
|
struct Base {
|
||||||
|
int f() { return 0; }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Derived : public Base {
|
||||||
|
int f() { return 1; }
|
||||||
|
};
|
||||||
|
|
||||||
|
Base *bp;
|
||||||
|
|
||||||
|
Base b;
|
||||||
|
bp = &b;
|
||||||
|
assert(bp->f() == 0);
|
||||||
|
|
||||||
|
Derived d;
|
||||||
|
bp = &d;
|
||||||
|
// Base method called!
|
||||||
|
assert(bp->f() == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the derived signature is not compatible with the virtual,
|
||||||
|
// no polymorphism happens!
|
||||||
|
//
|
||||||
|
// Also see "covariant return" for compatibility of return types.
|
||||||
|
//
|
||||||
|
// This is why you should always use override to prevent such bugs.
|
||||||
|
{
|
||||||
|
struct Base {
|
||||||
|
virtual int f() { return 0; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class Derived : public Base {
|
||||||
|
virtual int f(int i) /* override */ { return i; }
|
||||||
|
};
|
||||||
|
|
||||||
|
Base *bp;
|
||||||
|
|
||||||
|
Base b;
|
||||||
|
bp = &b;
|
||||||
|
assert(bp->f() == 0);
|
||||||
|
|
||||||
|
Derived d;
|
||||||
|
bp = &d;
|
||||||
|
// Base method called!
|
||||||
|
assert(bp->f() == 0);
|
||||||
|
|
||||||
|
// ERROR: no matching function.
|
||||||
|
#if 0
|
||||||
|
assert(bp->f(1) == 1);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Polymorphic calls cannot be made from constructors.
|
||||||
|
// https://stackoverflow.com/questions/1453131/how-can-i-get-polymorphic-behavior-in-a-c-constructor
|
||||||
|
{
|
||||||
|
struct Base {
|
||||||
|
int i;
|
||||||
|
Base() {
|
||||||
|
i = f();
|
||||||
|
}
|
||||||
|
virtual int f() { return 0; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class Derived : public Base {
|
||||||
|
int f() override { return i; }
|
||||||
|
};
|
||||||
|
|
||||||
|
Base b;
|
||||||
|
assert(b.i == 0);
|
||||||
|
|
||||||
|
Derived d;
|
||||||
|
assert(d.i == 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user