小编Arm*_*yan的帖子

使用智能指针返回类型协方差

在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++ virtual-functions smart-pointers return-type

32
推荐指数
1
解决办法
6459
查看次数

虚拟调度实施细节

首先,我想清楚地表明我确实理解在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的虚拟基类)

提前致谢.

c++ vtable vptr

31
推荐指数
2
解决办法
7495
查看次数

如何声明__stdcall函数指针

我试过这个

typedef void (* __stdcall MessageHandler)(const Task*);
Run Code Online (Sandbox Code Playgroud)

这编译但给了我这个警告(VS2003):

警告C4229:使用的时间错误:忽略数据上的修饰符

我想用stdcall调用约定声明一个指向函数的指针?我究竟做错了什么?

c++ function-pointers calling-convention visual-c++

31
推荐指数
1
解决办法
2万
查看次数

i = i ++不会增加i.为什么?

可能重复:
为什么会进入无限循环?

类似于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)

你能帮我理解为什么吗?

免责声明: 我完全清楚,无论是否定义了上述结构的行为,它们都是愚蠢,无用,不可读,不必要的,不应在代码中使用.我只是好奇.

c# increment

31
推荐指数
4
解决办法
1万
查看次数

生成m [0..n-1]范围内的m个不同随机数

我有两种方法在[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是否更有效?(根据运行时间的数学期望)

c++ random algorithm performance

31
推荐指数
4
解决办法
3万
查看次数

为什么常量指针不能成为常量表达式?

以下程序编译:

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)

c++ pointers constant-expression c++11

30
推荐指数
1
解决办法
4104
查看次数

非静态成员作为非静态成员函数的默认参数

struct X
{
   X():mem(42){}
   void f(int param = mem) //ERROR
   {
      //do something
   }
private: 
   int mem;
};
Run Code Online (Sandbox Code Playgroud)

任何人都可以给我一个原因,为什么这在C++中是非法的?!也就是说,我知道这是一个错误,我知道错误意味着什么,我只是无法理解为什么这是非法的!

c++ member-functions default-value

28
推荐指数
3
解决办法
4948
查看次数

零长度位域的实际应用

我不完全确定C,但C++允许未命名的0字段位字段.例如:

struct X
{
    int : 0;
};
Run Code Online (Sandbox Code Playgroud)
  • 问题一:您能想到的实际用途是什么?
  • 问题二:你知道什么是现实世界的实际用途(如果有的话)?

在冰犯罪的回答之后编辑了这个例子

编辑:好的,多亏了目前的答案,我现在知道了理论目的.但问题是关于实际用途,所以他们仍然持有:)

c c++ bit-fields

26
推荐指数
4
解决办法
5242
查看次数

关于shared_from_this的问题

我有一个功能,需要一个shared_ptr<MyClass>.在某些成员函数memfunMyClass,我需要传递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++ shared-ptr

24
推荐指数
2
解决办法
9985
查看次数

函数返回指针自身?

在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++

24
推荐指数
3
解决办法
4574
查看次数