在C++中我们可以这样做:
struct Base
{
virtual Base* Clone() const { ... }
virtual ~Base(){}
};
struct Derived : Base
{
virtual Derived* Clone() const {...} //overrides Base::Clone
};
Run Code Online (Sandbox Code Playgroud)
但是,以下内容不会做同样的伎俩:
struct Base
{
virtual shared_ptr<Base> Clone() const { ... }
virtual ~Base(){}
};
struct Derived : Base
{
virtual shared_ptr<Derived> Clone() const {...} //hides Base::Clone
};
Run Code Online (Sandbox Code Playgroud)
在此示例中Derived::Clone
隐藏 Base::Clone
而不是覆盖它,因为标准表示重写成员的返回类型可能仅从引用(或指针)更改为基础到引用(或指针).这有什么聪明的解决方法吗?当然有人可能认为Clone
函数应该返回一个普通的指针,但是现在让我们忘记它 - 这只是一个例证.我正在寻找一种方法来启用虚拟功能的返回类型从智能指针更改Base
为智能指针Derived
.
提前致谢!
更新:感谢 Iammilind,我的第二个例子确实无法编译
首先,我想清楚地表明我确实理解在C++标准中没有vtable和vptrs的概念.但是我认为几乎所有实现都以几乎相同的方式实现虚拟调度机制(如果我错了,请纠正我,但这不是主要问题).另外,我相信我知道虚函数是如何工作的,也就是说,我总能告诉我将调用哪个函数,我只需要实现细节.
假设有人问我以下内容:
"您的基类B具有虚函数v1,v2,v3和派生类D:B,它会覆盖函数v1和v3并添加虚函数v4.解释虚拟调度的工作原理".
我会这样回答:
对于每个具有虚函数的类(在本例中为B和D),我们有一个单独的指向函数的数组,称为vtable.
B的vtable将包含
&B::v1
&B::v2
&B::v3
Run Code Online (Sandbox Code Playgroud)
D的vtable将包含
&D::v1
&B::v2
&D::v3
&D::v4
Run Code Online (Sandbox Code Playgroud)
现在B类包含一个成员指针vptr.D自然地继承它,因此也包含它.在BB的构造函数和析构函数中设置vptr指向B的vtable.在DD的构造函数和析构函数中,它指向D的vtable.
对多态类X的对象x上的虚函数f的任何调用都被解释为对x.vptr的调用[f在vtables中的位置]
问题是:
1.我在上述描述中有任何错误吗?
2.编译器如何知道f在vtable中的位置(请详细说明)
3.这是否意味着如果一个类有两个基数那么它有两个vpt?在这种情况下发生了什么?(尝试以与我相似的方式描述,尽可能详细地描述)
4.钻石层次结构中发生了什么,其中A位于顶部B,C位于中间,D位于底部?(A是B和C的虚拟基类)
提前致谢.
我试过这个
typedef void (* __stdcall MessageHandler)(const Task*);
Run Code Online (Sandbox Code Playgroud)
这编译但给了我这个警告(VS2003):
警告C4229:使用的时间错误:忽略数据上的修饰符
我想用stdcall调用约定声明一个指向函数的指针?我究竟做错了什么?
可能重复:
为什么会进入无限循环?
类似于i = i++
C和C++中的未定义行为,因为标量对象的值在同一表达式中更改两次而没有插入序列点.
但是我认为这些表达式在C#或Java中具有明确定义的行为,因为AFAIK对参数的评估从左到右,并且全部都有序列点.
那就是说,我希望i = i++
相当于i++
.但事实并非如此.以下程序输出0
.
using System;
class Program
{
static void Main(string[] args)
{
int i = 0;
i = i++;
Console.WriteLine(i);
}
}
Run Code Online (Sandbox Code Playgroud)
你能帮我理解为什么吗?
免责声明: 我完全清楚,无论是否定义了上述结构的行为,它们都是愚蠢,无用,不可读,不必要的,不应在代码中使用.我只是好奇.
我有两种方法在[0..n-1]范围内生成m个不同的随机数
方法1:
//C++-ish pseudocode
int result[m];
for(i = 0; i < m; ++i)
{
int r;
do
{
r = rand()%n;
}while(r is found in result array at indices from 0 to i)
result[i] = r;
}
Run Code Online (Sandbox Code Playgroud)
方法2:
//C++-ish pseudocode
int arr[n];
for(int i = 0; i < n; ++i)
arr[i] = i;
random_shuffle(arr, arr+n);
result = first m elements in arr;
Run Code Online (Sandbox Code Playgroud)
当n远大于m时,第一种方法更有效,而第二种方法则更有效.但"更大"并不是一个严格的概念,是吗?:)
问题:我应该使用什么公式n和m来确定method1或method2是否更有效?(根据运行时间的数学期望)
以下程序编译:
template <const int * P>
class Test{};
extern const int var = 42; //extern needed to force external linkage
int main()
{
Test<&var> test;
}
Run Code Online (Sandbox Code Playgroud)
然而,这个没有,这对我来说是一个惊喜:
template <const int * P>
class Test{};
extern const int var = 42; //extern needed to force external linkage
extern const int * const ptr = &var; //extern needed to force external linkage
int main()
{
Test<ptr> test; //FAIL! Expected constant expression.
}
Run Code Online (Sandbox Code Playgroud)
替代示例:
int main()
{
const int size = 42;
int …
Run Code Online (Sandbox Code Playgroud) struct X
{
X():mem(42){}
void f(int param = mem) //ERROR
{
//do something
}
private:
int mem;
};
Run Code Online (Sandbox Code Playgroud)
任何人都可以给我一个原因,为什么这在C++中是非法的?!也就是说,我知道这是一个错误,我知道错误意味着什么,我只是无法理解为什么这是非法的!
我不完全确定C,但C++允许未命名的0字段位字段.例如:
struct X
{
int : 0;
};
Run Code Online (Sandbox Code Playgroud)
在冰犯罪的回答之后编辑了这个例子
编辑:好的,多亏了目前的答案,我现在知道了理论目的.但问题是关于实际用途,所以他们仍然持有:)
我有一个功能,需要一个shared_ptr<MyClass>
.在某些成员函数memfun
中MyClass
,我需要传递this
给该函数.但如果我写
void MyClass:memfun()
{
func(shared_ptr<MyClass>(this))
}
Run Code Online (Sandbox Code Playgroud)
我假设在呼叫结束后,引用计数将达到0并且this
将被尝试销毁,这是不好的.
然后我记得那个类enable_shared_from_this
有这个功能shared_from_this
.
所以现在我将使用以下内容:
class MyClass: public enable_shared_from_this<MyClass>
{
void MyClass:memfun()
{
func(shared_from_this());
}
};
Run Code Online (Sandbox Code Playgroud)
问题是:
1)绝对不可能在不衍生的情况下使用该功能enable_shared_from_this
吗?
2)是否enable_shared_from_this
意味着在具有自动存储持续时间的对象上调用memfun会导致不好的事情?例如
int main()
{
MyClass m; //is this OK?
m.memfun(); // what about this?
}
Run Code Online (Sandbox Code Playgroud)
3)如果我从MyClass派生,是否会正确继承enable_shared_from_this功能,还是需要再次派生?那是,
class MyCoolClass: public Myclass
{
void someCoolMember
{
someCoolFuncTakingSharedPtrToMyCoolClass(shared_from_this());
}
}
Run Code Online (Sandbox Code Playgroud)
这个可以吗?或者正确如下?
class MyCoolClass: public Myclass, public enable_shared_from_this<MyCoolClass>
{
void someCoolMember …
Run Code Online (Sandbox Code Playgroud) 在C++中是否可以编写一个返回指向自身的指针的函数?
如果不是,请提出一些其他解决方案以使以下语法有效:
some_type f ()
{
static int cnt = 1;
std::cout << cnt++ << std::endl;
}
int main ()
{
f()()()...(); // n calls
}
Run Code Online (Sandbox Code Playgroud)
这必须打印从1到1的所有数字n
.
c++ ×9
algorithm ×1
bit-fields ×1
c ×1
c# ×1
c++11 ×1
increment ×1
performance ×1
pointers ×1
random ×1
return-type ×1
shared-ptr ×1
visual-c++ ×1
vptr ×1
vtable ×1