考虑以下:
在Xh:
class X
{
X();
virtual ~X();
};
Run Code Online (Sandbox Code Playgroud)
X.cpp:
#include "X.h"
X::X()
{}
Run Code Online (Sandbox Code Playgroud)
尝试构建这个(我使用的是.dll目标,以避免在丢失的main上出现错误,我正在使用Visual Studio 2010):
错误1错误LNK2001:未解析的外部符号"private:virtual __thiscall X :: ~X(void)"(?? 1X @@ EAE @ XZ)
然而,小的修改导致成功构建:
XH:
class X
{
inline X(); // Now inlined, and everything builds
virtual ~X();
};
Run Code Online (Sandbox Code Playgroud)
要么
XH:
class X
{
X();
~X(); // No longer virtual, and everything builds
};
Run Code Online (Sandbox Code Playgroud)
当.dtor是虚拟的或者.ctor没有内联时,是什么导致链接器中未解析的外部?
编辑:
或者,或许更有趣的是,如果我将析构函数设置为非虚拟,或者如果我内联构造函数,为什么我没有得到未解析的外部?
我有一些C++代码(由其他人编写)似乎调用了错误的函数.情况如下:
UTF8InputStreamFromBuffer* cstream = foo();
wstring fn = L"foo";
DocumentReader* reader;
if (a_condition_true_for_some_files_false_for_others) {
reader = (DocumentReader*) _new GoodDocumentReader();
} else {
reader = (DocumentReader*) _new BadDocumentReader();
}
// the crash happens inside the following call
// when a BadDocumentReader is used
doc = reader->readDocument(*cstream, fn);
Run Code Online (Sandbox Code Playgroud)
条件为真的文件处理正常; 它是虚假崩溃的那些.DocumentReader的类层次结构如下所示:
class GenericDocumentReader {
virtual Document* readDocument(InputStream &strm, const wchar_t * filename) = 0;
}
class DocumentReader : public GenericDocumentReader {
virtual Document* readDocument(InputStream &strm, const wchar_t * filename) {
// some stuff …Run Code Online (Sandbox Code Playgroud) 在Java中:
class Base {
public Base() { System.out.println("Base::Base()"); virt(); }
void virt() { System.out.println("Base::virt()"); }
}
class Derived extends Base {
public Derived() { System.out.println("Derived::Derived()"); virt(); }
void virt() { System.out.println("Derived::virt()"); }
}
public class Main {
public static void main(String[] args) {
new Derived();
}
}
Run Code Online (Sandbox Code Playgroud)
这将输出
Base::Base()
Derived::virt()
Derived::Derived()
Derived::virt()
Run Code Online (Sandbox Code Playgroud)
但是,在C++中,结果是不同的:
Base::Base()
Base::virt() // ? Not Derived::virt()
Derived::Derived()
Derived::virt()
Run Code Online (Sandbox Code Playgroud)
(有关C++代码,请参阅http://www.parashift.com/c++-faq-lite/calling-virtuals-from-ctors.html)
什么导致Java和C++之间的这种差异?这是vtable初始化的时间吗?
编辑:我确实理解Java和C++机制.我想知道的是这个设计决定背后的见解.
给定以下代码片段,函数调用有何不同?什么是隐藏功能?什么是功能重写?它们如何与函数重载相关?两者有什么区别?我在一个地方找不到这些的好描述,所以我在这里问我所以我可以巩固这些信息.
class Parent {
public:
void doA() { cout << "doA in Parent" << endl; }
virtual void doB() { cout << "doB in Parent" << endl; }
};
class Child : public Parent {
public:
void doA() { cout << "doA in Child" << endl; }
void doB() { cout << "doB in Child" << endl; }
};
Parent* p1 = new Parent();
Parent* p2 = new Child();
Child* cp = new Child();
void testStuff() {
p1->doA();
p2->doA();
cp->doA(); …Run Code Online (Sandbox Code Playgroud) B类覆盖了A类的纯虚函数"print()".C类继承了B类,并且具有"使用A :: print"语句.既然C类不是抽象类呢?
class A {
public :
virtual void print() =0;
};
class B:public A {
public:
void print();
};
void B :: print() {
cout << "\nClass B print ()";
}
class C : public B {
public:
using A::print;
};
void funca (A *a) {
// a->print(1);
}
void funcb (B *b) {
b->print();
}
void funcc (C *c) {
c->print();
}
int main() {
B b;
C c;
funca(&c);
funcb(&c);
funcc(&c);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出:
Class …Run Code Online (Sandbox Code Playgroud) 在这个问题之后,我想知道为什么C++中的struct\class必须有一个虚方法才能变成多态.
强制虚拟析构函数是有道理的,但如果根本没有析构函数,为什么要使用虚方法呢?
为什么会这样?
http://coliru.stacked-crooked.com/a/e1376beff0c157a1
class Base{
private:
virtual void do_run() = 0;
public:
void run(){
do_run();
}
};
class A : public Base {
public:
// uplift ??
virtual void do_run() override {}
};
int main()
{
A a;
a.do_run();
}
Run Code Online (Sandbox Code Playgroud)
为什么我可以将PRIVATE虚方法覆盖为公共?
我有一个没有虚拟基类的多继承场景,如下所示:
Ta Tb
| |
B C
\ /
A
Run Code Online (Sandbox Code Playgroud)
Ta和Tb是两个不同的模板类,它们都声明了一个名为f()的虚函数.我想覆盖A范围中的两个函数,因为我必须在这些方法中与B和C数据进行交互.但我不知道该怎么做.
class Tb {
protected:
virtual void f() {};
public:
void call() {
this->f();
};
};
class Tc {
protected:
virtual void f() {};
public:
void call() {
this->f();
};
};
class B : public Tb {
public:
void doSomething() {};
};
class C : public Tc {
private:
int c;
public:
void inc() { c++; };
};
class A : public B, public C {
protected:
void f() { …Run Code Online (Sandbox Code Playgroud) 我有兴趣知道是否有任何可行的方法来连续存储多态对象数组,这样virtual可以合法地调用公共基础上的方法(并将调度到子类中正确的重写方法).
例如,考虑以下类:
struct B {
int common;
int getCommon() { return common; }
virtual int getVirtual() const = 0;
}
struct D1 : B {
virtual int getVirtual final const { return 5 };
}
struct D2 : B {
int d2int;
virtual int getVirtual final const { return d2int };
}
Run Code Online (Sandbox Code Playgroud)
我想分配一个连续的D1和D2对象数组,并将它们视为B对象,包括调用getVirtual()哪些将根据对象类型委托给适当的方法.从概念上讲,这似乎是可能的:每个对象通常通过嵌入的vtable指针知道它的类型,因此您可以想象,将n个对象存储在数组中,并使用放置和初始化对象,并将指针转换为.不过,我很确定演员不合法.n * max(sizeof(D1), sizeof(D2)) unsigned charnewdeleteunsigned charB*
人们还可以想象创建一个联盟,如:
union Both { …Run Code Online (Sandbox Code Playgroud) c++ ×10
overriding ×3
polymorphism ×2
arduino ×1
destructor ×1
firmware ×1
inheritance ×1
java ×1
oop ×1
overloading ×1
vptr ×1