具有void数据成员及其构造函数的类

时间:2015-08-11 06:27:38

标签: c++

我正在尝试编写在Windriver linux(64位)上运行的C ++应用程序。这是类似的代码:(我的代码的某些部分是自动生成的,我尽力使其保持相似)

#include <stdio.h>

class OneClass{
     const void *data;
     public:
       OneClass(const void *inData){

          printf("In normal const %u addr: %u\n", *((unsigned int*)(inData)), inData);

          data = inData;
       }

   OneClass(){
          printf("In default const\n");
      data = NULL;
       }

   OneClass(const OneClass &in){
          printf("In copy const\n");

          data = in.data;
       }

       const void* getData(){return data;}
};

OneClass create(const unsigned &in){
     printf("In create before %u\n", in);
     return new OneClass(&in);
}

main()
{
    OneClass two = create(100);
    unsigned int *value = (unsigned int*)two.getData();
    printf("In main %u\n", *value);
}

输出是:

In create before 100
In normal const 100 addr: 4294339016
In normal const 4294339016 addr: 134520840
In main 4294339016

我预计two.data是100,但它不是真的。怎么样?我还混淆了普通构造函数如何调用两次而不是复制构造函数?

任何人都可以帮助我吗?

2 个答案:

答案 0 :(得分:3)

OneClass(const void*)函数中隐式调用构造函数create。这是C ++的一个功能,允许隐式对象转换。

create的返回类型为OneClass。但是,您返回new OneClass(&in)。这是指向对象的指针,而不是对象本身(它的类型是OneClass*)。此指针传递给OneClass(const void*)构造函数,另一个OneClass使用OneClass*指针创建。这就是你的构造函数被调用两次的原因。

使用explicit关键字限定单个参数构造函数总是一个好主意,如下所示:

explicit OneClass(const void *inData)

现在,这段代码

OneClass create(const unsigned &in){
     printf("In create before %u\n", in);
     return new OneClass(&in);
}

将导致编译器错误,您可以捕获这样的细微错误。

此修订后的代码有效:

#include <cstdio> // you shouldn't include <stdio.h>, that's for C, not C++

class OneClass{
     const void *data;
     public:
       explicit OneClass(const void *inData){
          printf("In normal const %u addr: %p\n", // use the %p specifier to print pointers
                 *((unsigned int*)(inData)), inData); 
          data = inData;
       }

   OneClass(){
          printf("In default const\n");
      data = NULL;
       }

   OneClass(const OneClass &in){
          printf("In copy const\n");

          data = in.data;
       }

       const void* getData(){return data;}
};

OneClass* create(const unsigned &in){
     printf("In create before %u\n", in);
     return new OneClass(&in);
}

int main()
{
    OneClass* two = create(100);
    unsigned int *value = (unsigned int*)(*two).getData();
    printf("In main %u\n", *value);
}

或者放弃动态内存分配(可能非常麻烦,非常快)使用它:

OneClass create(const unsigned &in){
     printf("In create before %u\n", in);
     return OneClass(&in);
}

int main()
{
    OneClass two = create(100);
    unsigned int *value = (unsigned int*)two.getData();
    printf("In main %u\n", *value);
}

我建议你使用第二个。除非您特别需要使用new分配内容,否则您不应该这样做。

答案 1 :(得分:1)

问题是create函数,您似乎来自Java或C#背景,并将这些语言中的习语带到C ++,这些习惯用法在C ++中的工作方式与它们不同用Java或C#做。

在C ++中,您不需要使用new来创建对象实例,new所做的是分配内存并向其返回指针。以下是您遇到的问题:从create返回的对象使用您通过执行new OneClass(...)分配的指针进行初始化。

简单的解决方案是删除new运算符:

return OneClass(...);