微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

与C中的对象数组混淆

所以我首先学习了 Java,现在我试图切换到C.让数组正常工作有点困难.

现在我只是试图创建一个对象“Player”的数组,并用一个填充它.但是我收到一个错误.

Player* players = new Player[1];
players[0] = new Player(playerWidth,playerHeight,20,1);

错误说:
操作数“=”匹配这些操作数.操作数类型为:Player = Player *

我不明白为什么这不工作?

解决方法

错误是说您正在尝试为变量分配一个错误类型的值.当错误说Player = Player *时,表示左侧的变量是Player,右侧的值是Player *.
players[0] = new Player(playerWidth,1);

问题类似于你要做的事情:

int x;
x = "Hello,World!";

左手和右手类型不匹配,并且没有自然转换,因此您会收到错误.

一个问题是您来自Java背景,Java使用指针很多但是隐藏了它们. C根本不隐藏它们.结果是C具有不同的语法来明确处理指针. Java摆脱了所有这些,大多数使用C的常规非指针语法来处理指针.

Java:                                  C++:

Player player = new Player();          Player *player = new Player();

Player player2;                        Player *player2 = nullptr;

** no equivalent in java **            Player player3;

player.foo();                          player->foo();

** no equivalent in java **            player3.foo();

** no equivalent in java **            *player;

** no equivalent in java **            &player2;

了解使用指针并直接与对象进行工作的区别非常重要:

Java:                                  C++:

Player a = new Player();               Player *a = new Player();
Player b = a;                          Player *b = a;
b.foo();                               b->foo();

在这代码中,只有一个对象,你可以通过a或b访问它,并没有什么区别,a和b都是同一个对象的指针.

C++:

Player c = Player();
Player d = c;
d.foo();

在这代码中有两个对象.他们是独特的,做某事不影响c.

如果在Java中,您了解到像“String”这样的“primitive”类型之间的区别,那么一个想法就是在C中所有对象都是原始的.如果我们回顾你的代码,并使用这个’C对象就像Java原语’规则,你可能会看到更好的是什么问题:

Java:
int[] players = new int[1];
players[0] = new int(playerWidth); // huh???

这应该清楚,任务的右侧应该只是一个Player值,而不是一个新的玩家对象的动态分配.对于java中的int来说,这看起来像玩家[0] = 100;由于Java中的对象类型不同Java没有办法通过写入int值的方式写入Object值.但是C呢player [0] = Player(playerWidth,1);

第二个问题是C中的数组是奇怪的,C继承.

C和C中的指针允许“指针算术.如果您有一个指向对象的指针,您可以添加或减少对象,并获取指向其他对象的指针. Java没有什么类似的.

int x[2]; // create an array of two ints,the ints are 'adjacent' to one another
// if you take the address for the first one and 'increment' it
// then you'll have a pointer to the second one.

int *i = &x[0]; // i is a pointer to the first element
int *j = &x[1]; // j is a pointer to the second element

// i + 1 equals j
// i equals j - 1

另外,数组索引运算符[]适用于指针. x [5]等价于*(x 5).这意味着指针可以用作数组,这在C和C中是惯用的和预期的.其实它甚至被烤成了C.

在C中,当您使用新的动态分配对象,例如新玩家,你通常会得到一个指向你指定的类型的指针.在此示例中,您将获得Player *.但是当您动态分配数组时,例如新玩家[5],这是不同的.而不是返回一个指向五个玩家数组的指针,您实际上会获得一个指向第一个元素的指针.这就像任何其他玩家*:

Player *p   = new Player;    // not an array
Player *arr = new Player[5]; // an array

唯一使这个指针不同的是当你对它进行指针运算时,你会获得指向有效的Player对象的指针:

Player *x = p + 1;   // not pointing at a valid Player
Player *y = arr + 3; // pointing at the fourth array element

如果您在没有保护的情况下使用它们,则新建和删除将很难正确使用为了证明这一点:

int *x = new int;
foo();
delete x;

代码容易出错,可能是错误的.具体来说,如果foo()抛出一个异常,那么x被泄漏.

在C任何时候,如果你收到一个责任,比如当你打电话给你时,你会收到以后调用delete的责任,你应该记住

R.A.I.I.
Responsibility* Acquisition Is Initialization

更多的人说“资源获取是初始化”,但资源只是一种责任.在他的Exception Safe C++次谈判中,我被劝说使用后者Jon Kalb.

R.A.I.I.意味着每当你获得责任时,它应该看起来像你正在初始化一个对象;具体来说,您正在初始化一个特殊对象,其目的是为您管理该责任.这种类型的一个例子是std :: unique_ptr< int>它将管理分配给new的int指针:

C++:

std::unique_ptr<int> x(new int);
foo();
// no 'delete x;'

要管理你的Player数组,你可以使用std :: unqiue_ptr这样:

std::unique_ptr<Player[]> players(new Player[1]);
players[0] = Player(playerWidth,1);

现在,unique_ptr将为您处理该分配,您不需要自己调用delete. (N.B.当你分配一个数组时,你应该给unique_ptr一个数组类型; std :: unique_ptr< Player []>,当你分配任何你使用非数组类型时,std :: unique_ptr< Player&gt ;.) 当然,C有一个更专业的R.A.I.I.用于管理数组的类型,std :: vector,您应该更喜欢使用std :: unique_ptr:

std::vector<Player> players(1);
players[0] = Player(playerWidth,1);

或者在C 11:

std::vector<Player> players { Player(playerWidth,1) };

原文地址:https://www.jb51.cc/c/111929.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐