【问题标题】:C++ CLI Class problemC++ CLI 类问题
【发布时间】:2011-03-11 23:14:19
【问题描述】:

-----你好,世界 2.cpp -----

// Hello, World 2.cpp : main project file.

#include "stdafx.h"
#include "hello.h"
#include <string>

using namespace System;
using namespace std;

int main(array<System::String ^> ^args)
{
    hello hi = new hello("Bob", "Blacksmith");
    Console::WriteLine(L"Hello, " + hi.getName + "!");
    return 0;
}

--你好.h -----

#include <string>
using namespace std;

#ifndef HELLO_H
#define HELLO_H

class hello
{
private:
    string _fname;
    string _lname;
    //hello() { } // private default constructor

public:
    hello(string fname, string lname);
    void SetName(string fname, string lname);
    string GetName();

};

#endif

----- hello.cpp -----

#include "stdafx.h"
#include "hello.h"
#include <string>
using namespace std;

hello::hello(string fname, string lname)
{
    SetName(fname, lname);
}

void hello::SetName(string fname, string lname)
{
    _fname = fname;
    _lname = lname;
}

string hello::getName()
{
    return _fname + _lname;
}

----- 错误-----

  • ----- 构建开始:项目:Hello, World 2,配置:调试 Win32 ------
  • 你好,世界 2.cpp
  • 你好,世界 2.cpp(12):错误 C2440:“正在初始化”:无法从“你好 *”转换为“你好”
  • 没有构造函数可以采用源类型,或者构造函数重载决策不明确
  • 你好,世界 2.cpp(13):错误 C2039:“getName”:不是“hello”的成员
  • \documents\visual studio 2010\projects\cpp\hello, world 2\hello, world 2\hello.h(8) : 参见“hello”的声明
  • hello.cpp
  • hello.cpp(17): error C2039: 'getName' : is not a member of 'hello'
  • \documents\visual studio 2010\projects\cpp\hello, world 2\hello, world 2\hello.h(8) : 参见“hello”的声明
  • hello.cpp(19):错误 C2065:“_fname”:未声明的标识符
  • hello.cpp(19):错误 C2065:“_lname”:未声明的标识符
  • 正在生成代码... ========== 构建:0 成功,1 失败,0 最新,0 跳过 ==========

【问题讨论】:

    标签: c++-cli


    【解决方案1】:

    错误消息会准确地告诉您问题出在哪里以及问题出在哪里,尽管它们一开始可能有点吓人。也许我可以帮助揭开它们的神秘面纱:

    Hello, World 2.cpp(12): error C2440: 'initializing' : cannot convert from 'hello *' to 'hello'

    这意味着在 Hello, World 2.cpp 的第 12 行,您试图将指向 hello 的指针(从 new 返回)放在不是指针类型的 hi 内。由于此处不需要动态分配的对象,因此只需删除 new

    在您确实需要动态分配的对象的情况下,您可以将hi 变量更改为hello * 并添加相应的delete

    Hello, World 2.cpp(13): error C2039: 'getName' : is not a member of 'hello'

    C++ 区分大小写。在一个文件中有GetName,在另一个文件中有getName。选择一个。

    hello.cpp(19):错误 C2065:'_fname':未声明的标识符 hello.cpp(19): 错误 C2065: '_lname' : 未声明的标识符

    hello.cpp的第19行是小写getName的定义。由于getName 没有在类中声明(参见前面的错误),编译器不知道_fname_lname 是什么。一旦解决了原来的问题,这些错误就会消失。

    编辑

    请参阅 @Sergey 的回答,了解有关要解决的问题的其他一些更一般性的观察。

    【讨论】:

      【解决方案2】:

      new 关键字创建一个指针 - 如果你这样做,'hi' 应该声明为 hello*,或者你应该重新定义声明:

      hello hi(...);
      

      第二个错误只是由于区分大小写(getName,GetName)。

      【讨论】:

        【解决方案3】:
        hello hi = new hello("William", "Dyson");  
        

        必须是

        hello* hi = new hello(...);   
        

        或者

         hello hi("William", "Dyson");  ;
        
        Console::WriteLine(L"Hello, " + hi.getName + "!");
        

        必须

        Console::WriteLine(L"Hello, " + hi.getName() + "!");
        

        可能还有其他失败,但我现在必须走了。

        【讨论】:

        • L"你好,"?这不是隐式转换为 Char*,然后转换为 System::String 的宽字符串文字吗?
        【解决方案4】:

        有几个错误。

        • 带有空格的文件名。不重要,但可能会导致问题
        • Console::WriteLine(L"Hello, " + hi.getName + "!");

        这应该是这样的:

         string s("Hello, ");
         s += hi->getName();
         s += "!"
         Console::WriteLine(s);
        
        • 删除新分配的对象:delete hi;

        • string hello::getName() 应该是string hello::GetName()

        • 切勿在头文件中使用use namespace ...

        • 在保护块中包含其他文件

        【讨论】:

          【解决方案5】:

          如果您使用new 分配某些东西,您必须在不再需要它之后调用delete

          如果您想使用垃圾收集器进行清理,您必须将类声明为ref class hello,然后使用以下命令对其进行实例化:

          hello^ hi = gcnew hello(...);   
          

          【讨论】:

            【解决方案6】:

            在我写完之前肯定会发布一些 cmet:

            1. 将公共成员放在首位
            2. 命名空间System 暗示托管C++,如果你不知道那是什么并且认为你使用的是普通C++,请阅读printfstd::cout
            3. 线

              hello hi = new hello("William", "Dyson");

              应该阅读

              hello hi("William", "Dyson");hello* hi = new hello("William", "Dyson");

              第一个在堆栈上创建一个对象(当它超出范围时将自动销毁。第二个在堆上创建一个指向对象的指针,您必须在指针离开之前delete范围(完成后)

            4. 关于hello::getName():您在大小写方面有拼写错误(getname vs getName),应该这样声明(在标题中,相应地在源文件中):

              const string getName() const;

              第一个 const 是可选的,但我喜欢这样,最后一个允许您从 const hello 对象调用此函数,并告诉读者该函数不会修改该对象。

            5. 你应该通过引用传递string(这里是一个更正的构造函数):

              hello( const string &amp;fname, const string&amp; lname);

            6. 源和标头的名称中不应包含空格(或特殊字符),如果您不小心,这对于 UNIXWindows 会产生问题。

            这就是我现在所能看到的。

            【讨论】:

            • 公众会员优先与否只是个人喜好问题。而且 printf() 不是 C++。
            • “你应该通过引用传递字符串”:如果字符串没有在函数内部被复制,这是更好的建议。如果您打算制作副本,最好将副本设为隐式(按值传递)并让编译器找出最佳优化方式。
            • @codymanix:同意,但很多人使用它。我像躲避瘟疫一样避而远之。 @ Cogwheel:同意,但养成尽可能多地传递const 引用的习惯不会有什么坏处。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-10-10
            • 1970-01-01
            • 1970-01-01
            • 2011-08-05
            相关资源
            最近更新 更多