假设我的钻石继承情况如下:
class A{
public: virtual void foo(){};
};
class B: public virtual A{
public: virtual void foo(){};
};
class C: public virtual A{
public: virtual void foo(){};
};
class D: B, C{};
Run Code Online (Sandbox Code Playgroud)
引用歧义的最后一行产生编译错误.据我所知,问题是编译器不知道在D的vtbl中放置哪个foo,但是如果它没有定义自己的任何虚函数,为什么D甚至会有一个vtbl呢?
对于其clas(子)具有单继承的对象,通常需要多少个vptrs,其基类为多个继承base1和base2.确定对象提供了多少个vpt的策略是什么,它提供了几个单继承和多继承.虽然标准没有指定vptrs,但我只是想知道一个实现如何实现虚函数.
这个问题是我头脑中隐藏的一大疑问,也难以用言语来描述.有时似乎很明显,有时候很难破解.所以问题就像这样::
class Base{
public:
int a_number;
Base(){}
virtual void function1() {}
virtual void function2() {}
void function3() {}
};
class Derived:public Base{
public:
Derived():Base() {}
void function1() {cout << "Derived from Base" << endl;
virtual void function4() {cout << "Only in derived" << endl;}
};
int main(){
Derived *der_ptr = new Derived();
Base *b_ptr = der_ptr; // As just address is being passed , b_ptr points to derived object
b_ptr -> function4(); // Will Give Compilation ERROR!!
b_ptr -> function1(); … gsoap及其工具wsdl2h和soapcpp2为我提供了一个包含以下内容的soapStub.h文件:
class SOAP_CMAC ns2__SOAPKunden
{
public:
std::string *adresszusatz;
// ...
public:
virtual int soap_type() const { return 7; }
// ...
ns2__SOAPKunden() : adresszusatz(NULL), x(NULL) { } // left out all member init.
virtual ~ns2__SOAPKunden() { }
};
Run Code Online (Sandbox Code Playgroud)
我从一个小应用程序开始,使用该类用informix DB中的数据填充对象.
但要成功编译我必须放弃所有的虚拟东西 - 我发现很多关于这个错误的帖子和在子类中使用虚拟成员 - 否则我得到
main.o: In function `ns2__SOAPKunden::ns2__SOAPKunden()':
main.cpp:(.text._ZN15ns2__SOAPKundenC1Ev[ns2__SOAPKunden::ns2__SOAPKunden()]+0xf): undefined reference to `vtable for ns2__SOAPKunden'
main.o: In function `ns2__SOAPKunden::~ns2__SOAPKunden()':
main.cpp:(.text._ZN15ns2__SOAPKundenD1Ev[ns2__SOAPKunden::~ns2__SOAPKunden()]+0x13): undefined reference to `vtable for ns2__SOAPKunden'
collect2: ld returned 1 exit status
Run Code Online (Sandbox Code Playgroud)
我承认经过多年的脚本编写后,我很难理解C++代码......我想问一下下一步要做什么的建议.我的班级没有派生类,例如让我惊讶的是什么.
我正在处理C++中的继承.我想编写一个程序来加减两个数组.继承我的代码:
#include <iostream>
#include <cmath>
#include <sstream>
using namespace std;
class root
{
protected :
int size;
double *array;
public :
virtual ~root() {}
virtual root* add(const root&) = 0;
virtual root* sub(const root&) = 0;
virtual istream& in(istream&, root&) = 0;
virtual int getSize() const = 0;
virtual void setSize(int);
virtual int getAt(int) const = 0;
};
class aa: public root
{
public :
aa();
aa(int);
aa(const aa&);
root* add(const root& a);
root* sub(const root& a);
istream& in(istream&, root&){} …Run Code Online (Sandbox Code Playgroud) 这是简单的类定义,如
class Base{
public:
virtual void Func(){
cout<<"Func in Base"<<endl;
}
};
class Derived : public Base{
public:
virtual void Func(){
cout<<"Func in Derived"<<endl;
}
}
Base *b = new Derived();
Run Code Online (Sandbox Code Playgroud)
和声明
(b->*&Base::Func)();
Run Code Online (Sandbox Code Playgroud)
调用Func的派生版本,不同于b-> Base :: Func(),它按预期调用基本版本,为什么会发生这种情况,这个调用的含义到底是什么?
想象一个项目,其中有一个如下所示的接口类:
struct Interface
{
virtual void f()=0;
virtual void g()=0;
virtual void h()=0;
};
Run Code Online (Sandbox Code Playgroud)
假设其他地方,有人希望创建一个类实现这个接口,为此f,g,h都做同样的事情.
struct S : Interface
{
virtual void f() {}
virtual void g() {f();}
virtual void h() {f();}
};
Run Code Online (Sandbox Code Playgroud)
然后,它会生成一个虚函数表的有效优化S其条目都指向S::f,从而节省的包装函数的调用g和h.
但是,打印vtable的内容表明不执行此优化:
S s;
void **vtable = *(void***)(&s); /* I'm sorry. */
for (int i = 0; i < 3; i++)
std::cout << vtable[i] << '\n';
Run Code Online (Sandbox Code Playgroud)
0x400940
0x400950
0x400970
与clang和gcc之间的切换一样编译-O3或-Os …
我试图通过虚拟表和继承来解决一些低级别的问题.
通过继承两个类并添加新的虚函数来创建新类时,vptr将存储在哪里?
在我看来,编译器在这种情况下执行一些'vptr-optimization'.而我正想弄明白.
假设,我们有以下结构:
struct A
{
int a;
virtual void fa();
};
struct B
{
double b;
virtual void fb();
};
struct C : A, B
{
char c;
virtual void fa();
virtual void fb();
virtual void fc();
};
Run Code Online (Sandbox Code Playgroud)
在86的情况下和对齐= 4,A并且B在存储器中看起来像这样:
+------+------+
A: | vptr | a |
+------+------+
sizeof(A) = 4 + 4 = 8
+------+------+------+------+
B: | vptr | b |
+------+------+------+------+
sizeof(B) = 8 + 8 = 16
Run Code Online (Sandbox Code Playgroud)
但是当我尝试重新组装时C,我得到了这个:
+------+------+------+------+------+------+------+ …Run Code Online (Sandbox Code Playgroud) 有人可以解释这个不同类的虚拟表是如何存储在内存中的吗?当我们使用指针调用函数时,他们如何使用地址位置调用函数?我们可以使用类指针获取这些虚拟表内存分配大小吗?我想看看一个类的虚拟表使用了多少内存块.我怎么能看到它?
class Base
{
public:
FunctionPointer *__vptr;
virtual void function1() {};
virtual void function2() {};
};
class D1: public Base
{
public:
virtual void function1() {};
};
class D2: public Base
{
public:
virtual void function2() {};
};
int main()
{
D1 d1;
Base *dPtr = &d1;
dPtr->function1();
}
Run Code Online (Sandbox Code Playgroud)
谢谢!提前
Rust的trait对象是胖指针,包含2个常规指针:数据和vtable.vtable是一个包含析构函数指针,所有特征方法指针以及最后数据大小和对齐的结构.
大小和对齐字段是什么?
我找不到多少:
vtable ×10
c++ ×9
vptr ×3
inheritance ×2
polymorphism ×2
dynamic ×1
gsoap ×1
oop ×1
rust ×1
virtual ×1