c++ 中的实例化
首先,我想通知您,我已经明确搜索了以下问题的答案,但我是 C++ 的新手。
我刚刚摆脱了 C# 和 Java 的奢侈生活,现在正在尝试了解有关 c++ 的一两件事
。问题是关于实例化的。
我使用 code::block 作为我选择的 IDE。
(我实际上非常熟悉并且已经编写了几个应用程序),即
目前我只是在玩 C# 中的两个类
包含 main 和 Person 的类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Models.Person;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Person person = new Person();
Console.WriteLine(person.getName());
}
}
}
以及 person 类:(
namespace ConsoleApplication1
{
public class Person{
private string name = "Bob";
public string getName(){
return name;
}
}
}
不要介意错误或正确的书面语法,它的只是为了模拟我想要实现的目标)
我想在 C++ 中实现相同的目标
,我已经查找过,并在一定程度上了解了标头,并掌握了一些语法。这就是我现在所拥有的。
main.cpp
#include <iostream>
using namespace std;
int main()
{
Person person;
cout << person->getName() << endl;
}
Person.h
#ifndef PERSON_H
#define PERSON_H
#include <string>
class Person
{
public:
Person();
virtual ~Person();
std::string getName();
protected:
private:
};
#endif // PERSON_H
player.cpp
#include "Person.h"
#include <string>
using std::string;
Person::Person()
{
//ctor
}
Person::~Person()
{
}
string Person::getName()
{
return name;
}
考虑到上面的代码,我有多个问题。
我从来没有找到一个好的来源来告诉我是否应该使用 Person person;
或 Person person = new Person();
实例
化,两者中哪一个是我的我应该使用吗?
我非常想知道的另一个问题是,我是在头文件中还是在类文件中定义类成员?
目前我收到以下错误:
“person”未在范围内声明,应为“;”人前
我不一定要求您解决我的错误,我会在收到我的问题的答案后进行解决。
First of all, I would like to notify you, I have definetly searched for answers about my following question, but im a complete newbie to C++.
I am coming from the luxurious life of C# and Java, now trying to pick up a thing or two about c++
The question is about instantiation.
I use code::block as my IDE of choice.
Currently I am just playing around with what in C# (which I'm actually quite familiar with and have written several applications in) is
2 classes
the class containing main and Person
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Models.Person;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Person person = new Person();
Console.WriteLine(person.getName());
}
}
}
and the person class:
namespace ConsoleApplication1
{
public class Person{
private string name = "Bob";
public string getName(){
return name;
}
}
}
(dont mind bad or right written syntax, its just to simulate what i want to achieve)
I want to achieve the same in C++
I have looked up, and learned about headers to some extent, and picked up a bit of the syntax. This is what I have right now.
main.cpp
#include <iostream>
using namespace std;
int main()
{
Person person;
cout << person->getName() << endl;
}
Person.h
#ifndef PERSON_H
#define PERSON_H
#include <string>
class Person
{
public:
Person();
virtual ~Person();
std::string getName();
protected:
private:
};
#endif // PERSON_H
player.cpp
#include "Person.h"
#include <string>
using std::string;
Person::Person()
{
//ctor
}
Person::~Person()
{
}
string Person::getName()
{
return name;
}
Considering the above code, I have multiple questions.
I never found a good source that showed me whether I should instantiate using Person person;
or Person person = new Person();
Which one of the two is the one I'm supposed to use?
And another question I'm dying for is, do I define class members in the header file or in the class file?
Currently I'm recieving the following errors:
'person' was not declared in scope and expected ';' before person
I'm not nescesarily asking you to resolve my errors, I'll manage that upon recieving answers on my questions.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
正如 larsmans 所说,
Person person
和Person *person = new Person()
会导致新的Person
实例在堆栈/堆中分配分别。这对您意味着什么(这是“我应该使用哪个?”问题的答案)是,在第一种情况下,对象的内存是自动管理的(这是好消息)。坏消息是对象的生命周期也是自动管理的,并且您无法控制它。一旦
person
变量超出范围,该对象就会被销毁。时期。在第二种情况(
new
)中,对象的生命周期由您管理(它将一直存在,直到您删除 person
)。这里的坏消息是内存也由您管理:如果您不执行delete person
,分配给该对象的内存将会泄漏。如果您不再在范围内的任何地方引用person
,那不会有任何区别。因此,如果生命周期对您来说足够长,请不要使用指针。否则,你将不得不这样做。
对于类成员:
一般来说,定义应该放在
.cpp
文件中,但如果您在标头中定义非常短的方法也没关系。附录
当然,在这个简短的回答中,还有很多细节我没有提及。以下是您可能需要研究的一些重要问题:
new
/delete
来管理内存,除了内存泄漏之外,还会产生许多其他问题; 悬空指针(指向已被释放的内存,因此不能再使用——这本质上是内存泄漏的“反向”错误)可能是列表中的第二名。IDisposable
)。您可以在 C++0x 和 Boost 中使用非常好的、成熟的智能指针。a
占用 2MB 内存,而您执行b = a
,则编译器只需使用a
的副本填充全新的 2MB 内存code> (并且可能需要做很多额外的工作来实现这一点)。如果这不是您的意图,您需要存储一个指向a
的指针或引用。As larsmans said,
Person person
andPerson *person = new Person()
are result in the newPerson
instance being allocated in the stack/heap respectively.What this means for you (and this is the answer to the "which should I use?" question) is that in the first case, the memory for the object is managed automatically (that's the good news). The bad news is that the lifetime of the object is also managed automatically, and you don't have any control over it. As soon as the
person
variable goes out of scope, the object is destroyed. Period.In the second case (
new
), the object's lifetime is managed by you (it will exist until you dodelete person
). The bad news here is that the memory is also managed by you: if you don't ever dodelete person
, the memory allocated to that object will leak. It won't make any difference if you have no reference toperson
anywhere in scope anymore.So if the lifetime is long enough for you, don't use a pointer. Otherwise, you will have to.
For class members:
Generally definitions should go to the
.cpp
file, but it's OK if you define really short methods in the header.Addendum
Of course there are plenty of details I didn't touch upon in this short answer. Here's a few important ones you might want to look into:
new
/delete
to manage memory can also give birth to lots of other problems apart from memory leaks; dangling pointers (which point to memory that has been released, and therefore cannot be used anymore -- this is essentially the "reverse" error than a memory leak) is probably #2 on the list.IDisposable
). There are very good and mature smart pointers you can use in C++0x and Boost.a
takes up 2MB of memory and you dob = a
, you just had the compiler populate a brand new 2MB of memory with a copy ofa
(and probably do a lot of extra work to achieve that). If that is not your intention, you need to store a pointer or a reference toa
instead.Person person
将在堆栈上构造一个对象。Person *person = new Person
将在空闲存储的内存中构造它(堆;注意*
因为您需要一个指针)。这与 C# 不同,在 C# 中,您可以在struct
和class
之间进行选择来获取堆栈或堆分配。在 C++ 中,这些关键字具有不同的含义。如果您选择在堆上分配,则稍后必须手动删除
该对象。(请不要将
using
指令放在头文件的顶层。)Person person
will construct an object on the stack.Person *person = new Person
will construct it in memory on the free store (heap; note the*
because you need a pointer). This differs from C#, where you'd choose betweenstruct
andclass
to get either stack or heap allocation. In C++, these keywords have a different meaning. If you choose to allocate on the heap, then you must laterdelete
the object manually.(Please don't put a
using
directive at top-level in a header file.)与 C# 代码等效的内容如下:
输出:
请参阅在线演示:http://ideone.com/cM0uU
The equivalent of your C# code would be this:
Output:
See the online demo : http://ideone.com/cM0uU
关于 Person 的主要区别是你是否想要价值
语义或引用语义——对于实体对象,引用
语义是必要的(因为它们保留身份),但是对于
对于大多数其他人来说,值语义是更可取的。在你的例子中,
人们可以很容易地使用值语义,但在
更现实的情况,这取决于班级的角色
在应用程序中。
不管怎样,如果你定义了值语义,你就不会(几乎)
从不)动态分配实例。您将它们定义为本地的
变量,根据需要复制它们,然后让编译器获取
照顾其余的。您还确保副本、作业和
析构函数做你想做的事——在现代 C++ 中,这通常是
这种情况,因为您的应用程序级别对象将基于
具有复制构造函数、赋值和
破坏做正确的事,但这在过去并不是这样
情况确实如此,但今天情况并非总是如此。如果你想
实体语义,你必须决定实体的生命周期
实体应该是。 (我会说就像你在其他
语言,但许多 Java 和 C# 程序员忘记了这一点。和
常常侥幸逃脱。你永远不会逃脱它的惩罚
C++。)实体对象通常使用 new 创建,并且必须
当他们的生命结束时就会被摧毁。
禁止实体的复制和转让也是一个好习惯
C++ 中的对象(除了可能提供克隆函数)。
关于第二点:完整的类定义必须
位于一个地方;你不能重新打开定义一次
你已经用最后一个大括号将其关闭了。这意味着
成员函数声明(但不是定义)和
成员数据必须存在于类定义中
头文件。最好是尽量少放
然而,头文件和函数的定义(
实现)通常属于源文件。
(所有这些规则都有例外,但它们是一个很好的
起点。)
The main distinction concerning Person is whether you want value
semantics or reference semantics---for entity objects, reference
semantics are necessary (since they preserve identity), but for
most others, value semantics are preferrable. In your example,
Person could easily be made to work with value semantics, but in
a more realistic case, it would depend on the role of the class
in the application.
Anyway, if you define value semantics, you do not (almost
never) allocate instances dynamically. You define them as local
variables, copying them as needed, and let the compiler take
care of the rest. You also make sure that copy, assignment and
the destructor do what you want---in modern C++, this is usually
the case, as your application level objects will be based on
lower level objects with copy constructors, assignment and
destruction which do the right thing, but this didn't used to be
the case, and it isn't always the case today. If you want
entity semantics, you have to decide what the lifetime of the
entity should be. (I'd say just as you would in other
languages, but many Java and C# programmers forget this. And
often get away with it. You won't get away with it, ever, in
C++.) Entity objects are normally created using new, and must
be destructed when their lifetime ends.
It's also good practice to ban copy and assignment of entity
objects (except maybe to provide a clone function) in C++.
Concerning the second point: the complete class definition must
be in a single place; you can't reopen the definition once
you've closed it with the last curly brace. This means that
member function declarations (but not the definitions) and
member data must be present in the class definition, in the
header file. It's best to put as little as possible in the
header file, however, and the definitions of the functions (the
implementation) normally belongs in the source file.
(There are exceptions to all of these rules, but they're a good
starting point.)
在 main.cpp 的开头,您还必须
#include "Person.h"
。In the beginning of main.cpp you must also
#include "Person.h"
.在java中,一切都是引用类型,因此必须使用new来实例化,它创建一个值类型并返回对其的引用。在c++中,基本类型是值类型,而类似于java的引用类型看起来像Person* person;当你进入c++时,你真的应该放弃你从java中学到的一切,并从基础开始,从高级到低级编程确实会非常令人困惑
In java, everything is a reference type, and so has to be instantiated using new, which creates a value type and returns a reference to it. In c++, the basic type is a value type, and a reference type similar to a java one looks like Person* person; You should really drop everything you know from java when going into c++ and start from the basics, it really can be very confusing to go from high to low level programming
如果您来自 C#,此解释可能会有所帮助:
在 C++ 中,类型的声明/定义不会说明它是“值类型”还是“引用类型”。 “struct”和“class”之间的唯一区别是“class”中的成员默认是私有的。这是你如何使用它决定的。
当您声明一个
Person
时,您将其创建为“值类型”。当您声明
Person*
时,您正在创建一个指向Person
的指针(C# 中的引用类型),该指针通常使用new
在堆上分配代码>. C++ 中的引用(即Person&
)类似于 C# 中的ref Person
。正如 James 在他的评论中指出的那样,获得一本好的 C++ 书籍是你最好的选择。
If you're coming from C#, this explaination might be helpful:
In C++ the declaration/definition of a type doesn't say whether it is a "value type" or a "reference type". The only difference between 'struct' and 'class' is that members are private by default in 'class'. It's how you use it that determines this.
When you declare a
Person
, you are creating it as a "value type".When you declare a
Person*
, you are creating a pointer (a reference type in C#) to aPerson
which normally is allocated on the heap withnew
. References (i.e.Person&
) in C++ are likeref Person
in C#.As James points out in his comment, getting a good C++ book is your best bet.
您收到的错误来自于未使用
#include "Player.h"
(假设这就是您为包含class Person
声明的头文件命名的名称,因为这就是您的#define PLAYER_H
建议)。之后,它会抱怨,因为您使用的是person->getName()
而不是person.getName()
。->
与指针一起使用,您可能应该阅读更多相关内容。至于定义类成员,如果我正确理解术语,您应该在头文件中声明它们。然后,它们通常在类文件的构造函数中隐式定义。
然后在类文件中:
当然,您可以在头文件中同时执行这两项操作,有时这样做是合适的。
The errors you're getting come from not using
#include "Player.h"
(assuming that's what you named the header file containing the declaration for theclass Person
since that's what your#define PLAYER_H
suggests). After that, it'll complain because you're usingperson->getName()
instead ofperson.getName()
. The->
is used with pointers you should probably read up a bit more on this.As for defining class members, if I understand the terminology correctly, you should declare them in your header file. They are then defined, often implicitly, in the constructor in your class file.
And then in the class file:
Of course, you can do both in the header file and it's appropriate to do so sometimes.