我读了很多人写的"一个虚拟表存在于一个已经在其中声明了虚函数的类".
我的问题是,vtable是仅存在于具有虚函数的类还是存在于从该类派生的类中.
例如
class Base{
public:
virtual void print(){cout<<"Base Print\n";}
};
class Derived:public Base{
public:
void print(){cout<<"Derived print\n";}
};
//From main.cpp
Base* b = new Derived;
b->print();
Run Code Online (Sandbox Code Playgroud)
问题:如果没有派生类的vtable,那么输出就不会是"派生打印".所以IMO存在一个vtable,用于任何已声明虚函数的类,也存在于从该类继承的类中.它是否正确 ?
目前尚不清楚如果我在C++ 0x中删除虚拟方法会发生什么:
virtual int derive_func() = delete;
Run Code Online (Sandbox Code Playgroud)
这是否意味着这个类,从它继承的所有东西都无法定义/实现该derive_func()方法?或者这是非法/编译错误?
我正在尝试半个永恒现在覆盖QT中的QWidgets keyPressEvent函数,但它只是不起作用.我要说我是CPP的新手,但我知道ObjC和标准C.
我的问题看起来像这样:
class QSGameBoard : public QWidget {
Q_OBJECT
public:
QSGameBoard(QWidget *p, int w, int h, QGraphicsScene *s);
signals:
void keyCaught(QKeyEvent *e);
protected:
virtual void keyPressEvent(QKeyEvent *event);
};
Run Code Online (Sandbox Code Playgroud)
QSGameBoard是我的QWidget子类,我需要覆盖keyPressEvent并在每个事件上触发SIGNAL以通知一些注册的对象.
我在QSGameBoard.cpp中重写的keyPressEvent如下所示:
void QSGameBoard::keyPressEvent(QKeyEvent *event) {
printf("\nkey event in board: %i", event->key());
//emit keyCaught(event);
}
Run Code Online (Sandbox Code Playgroud)
当我将QSGameBoard ::更改为QWidget ::它接收事件,但我无法发出信号,因为编译器抱怨范围.如果我像这样写它,函数根本不会被调用.
这有什么问题?
我试图找出当派生类将虚拟函数声明为私有时会发生什么.以下是我写的程序
#include <iostream>
using namespace std;
class A
{
public:
virtual void func() {
cout<<"A::func called"<<endl;
}
private:
};
class B:public A
{
public:
B()
{
cout<<"B constructor called"<<endl;
}
private:
void func() {
cout<<"B::func called"<<endl;
}
};
int main()
{
A *a = new B();
a->func();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
令人惊讶的是(对我来说)输出是:
B constructor called
B::func called
Run Code Online (Sandbox Code Playgroud)
这不是违反该功能的私人访问集.这是预期的行为吗?这是标准的解决方法还是漏洞?通过VTABLE解析函数调用时是否绕过了访问级别?
对此行为的任何了解都会非常有帮助.
此外,有人提到私有覆盖虚拟成员会阻止进一步的类继承它.即使这有问题.修改上述程序包括:
class C: public B
{
public:
void func() {
cout<<"C::func called"<<endl;
}
};
Run Code Online (Sandbox Code Playgroud)
以及主要的测试程序:
int main()
{
A *a = new …Run Code Online (Sandbox Code Playgroud) 我认为以下C++代码是正确的,但在使用"-Woverloaded-virtual"编译时会产生一些警告,警告是否存在或者此代码存在实际问题?
如果这是一个虚假的警告,我该怎么做才能避免它,在派生的get rids中定义所有异常虚拟变量,但也许是一个更好的解决方案
G ++命令:
g++ -c -Woverloaded-virtual test.cpp
test.cpp:22:18: warning: ‘virtual void intermediate::exception(const char*)’ was hidden [-Woverloaded-virtual]
test.cpp:32:18: warning: by ‘virtual void derived::exception()’ [-Woverloaded-virtual]
Run Code Online (Sandbox Code Playgroud)
C++代码
using namespace std;
class base
{
public:
virtual void exception() = 0;
virtual void exception(const char*) = 0;
};
class intermediate : public base
{
public:
virtual void exception()
{
cerr << "unknown exception" << endl;
}
virtual void exception(const char* msg)
{
cerr << "exception: " << msg << endl;
}
};
class …Run Code Online (Sandbox Code Playgroud) 希望这对StackOverflow的问题不太专业:如果是,可以在其他地方迁移,请告诉我......
很久以前,我写了一篇本科毕业论文提出了C++和相关语言的各种devirtualization技术,一般是根据代码路径(有点像模板)预编译专业化的想法,但与检查,以选择正确的专长是在情况下,运行时选择它们不能在编译时选择(因为模板必须是).
(非常)基本的想法类似于以下内容...假设你有一个类C如下的类:
class C : public SomeInterface
{
public:
C(Foo * f) : _f(f) { }
virtual void quack()
{
_f->bark();
}
virtual void moo()
{
quack(); // a virtual call on this because quack() might be overloaded
}
// lots more virtual functions that call virtual functions on *_f or this
private:
Foo * const _f; // technically doesn't have to be const explicitly
// as long as it can be proven not be modified
}; …Run Code Online (Sandbox Code Playgroud) c++ compiler-construction virtual-functions vtable compiler-optimization
看过一些相关的问题,但不是这个问题......
我把课程视为适合几个主要类别,让我们说这四个简单:
值类具有一些数据和一堆操作.可以复制它们并进行有意义的比较以获得相等性(通过预期副本相同==). 这几乎总是缺乏虚拟方法.
唯一的类,其实例具有禁用分配和复制的标识.通常没有operator==这些,因为你将它们作为指针进行比较,而不是作为对象. 这些通常有很多虚方法,因为没有对象切片的风险,因为你被迫通过指针或引用传递它们.
Unique-but-Clonable类禁用复制,但预先设计为支持克隆,如果这是你真正想要的. 它们具有虚拟方法,最重要的是遵循虚拟构造/克隆习语的方法
容器类继承他们持有的任何属性. 这些往往没有虚拟方法...例如参见"为什么STL容器没有虚拟析构函数?" .
无论持有这种非正式的信仰系统,我都尝试过将虚拟方法添加到可复制的东西中.虽然我可能认为如果"有效"会"真的很酷",但它不可避免地会破裂.
这让我想知道是否有人有一个具有虚拟方法并且不禁用复制的类型的实际好例子?
我是一名出色的 C 程序员,我用 C 编写了一个汇编程序和 VM(https://github.com/chucktilbury/assembler(大部分工作但不完整)),我正在考虑将其移植到 C++,以便我可以使用STL 的原因显而易见。这是一个业余爱好项目,并不期望对任何人都有用。
我的虚拟机有一个值的概念,它可以是多种类型中的一种。我已经使用嵌入了联合的结构来实现它。这导致了一堆巨大的宏来完成简单的事情,例如加法和比较。
我想做的是拥有一个可用于引用 Value 的基类和实现特定类型的子类,这样我就不必准确说明如何检索 Value 实现的数据。
换句话说,这就是我所拥有的:
...
switch(left_val->type) {
...
case FLOAT:
switch(right_val->type) {
...
case INTEGER:
result->type = FLOAT;
result->data.float_val = left_val->data.float_val + right_val->data.int_val;
break;
...
}
...
}
Run Code Online (Sandbox Code Playgroud)
我想看到的是:
result->add(left_val, right_val); // over-simplified, I know....
Run Code Online (Sandbox Code Playgroud)
显然,我可以像在 C 中那样做,这是我的下意识反应。但我觉得我错过了C++ 中应该如何工作的一些要点。
据我了解,没有办法实现我想要的,因为 C++(如 C)是一种静态类型语言。我也可以将丑陋的部分封装在一个类中,然后像我目前在 C 中所做的那样传递值。
大家普遍同意这个说法吗?还是我完全错了?
我有名为“Base”和“Derived”的类。
struct Base {
Base() = default;
virtual ~Base() = default;
Base(const Base&) = delete;
Base& operator=(const Base&) = delete;
virtual void DoStuff() = 0;
};
Run Code Online (Sandbox Code Playgroud)
“Base”类需要虚拟析构函数,这是可以理解的。我也不允许复制这个类
struct Derived : Base {
Derived() = default;
~Derived() override = default;
void DoStuff() override { /*...*/ }
};
Run Code Online (Sandbox Code Playgroud)
int main()
{
std::shared_ptr<Base> a = std::make_shared<Derived>();
a->DoStuff();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
现在让我们介绍一下其他的类,我不知道,Callable还有DerivedCallable
struct Callable
{
virtual void Call() = 0;
};
Run Code Online (Sandbox Code Playgroud)
struct DerivedCallable : Base, Callable
{
DerivedCallable() = default;
~DerivedCallable() …Run Code Online (Sandbox Code Playgroud) 通常从构造函数调用虚函数被认为是不好的做法,因为子对象中的被覆盖函数将不会被调用,因为尚未构造对象.
但是,请考虑以下类:
class base
{
public:
base() {}
~base() {}
private:
virtual void startFSM() = 0;
};
class derived final : public base
, public fsm_action_interface
{
public:
derived() : base{}
, theFSM_{}
{ startFSM(); }
/// FSM interface actions
private:
virtual void startFSM()
{ theFSM_.start(); }
private:
SomeFSMType theFSM_;
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,类derived被标记为,final因此不存在其他子对象.因此,虚拟调用将正确解析(到最派生类型).
它仍然被认为是不好的做法吗?
c++ ×10
c++11 ×2
inheritance ×2
vtable ×2
clone ×1
constructor ×1
copy ×1
dynamictype ×1
gcc ×1
overloading ×1
overriding ×1
polymorphism ×1
qt ×1