-3

这是我的代码:

#include <iostream>
#include <string>

using namespace std;

class C
{
private:
    string str;
    friend void func();
};


void func()
{
        str = "Lala";
        cout << str << endl;

}

int main()
{
    func();
}

我不明白为什么这不起作用。
在我更大的项目中,我想访问具有类外函数的类的私有变量。
这里我做了一个类 C 并做了一个函数 func(); 成为它的朋友。但我仍然不能在函数中使用它的私有变量。
我做错了什么,有没有更好的方法来做到这一点?

4

6 回答 6

4

它不起作用,因为void func();它不是类的成员函数,它只是被声明为它的友元函数,这意味着它可以访问私有成员。

您没有 的实例class C,因此您不可能引用任何有效str变量。

于 2013-06-29T13:35:14.410 回答
3

下一次,也请引用你得到的错误。在这种情况下,将出现一个编译错误,说明符号“str”尚未在 func() 中定义。

如果要访问 C 类实例的成员 str,则需要这样的实例,如:

void func(){
    C c;
    c.str = "Lala";
    cout << c.str << endl;

}
于 2013-06-29T13:35:22.037 回答
3

func()不是成员函数,并且它没有接收任何类型的参数,C应该对什么对象进行操作?

func必须是C(在这种情况下,您将在 的实例上调用它C,并且friend不是必需的)的成员函数,或者是接收某些类型参数的函数C(或创建本地C对象),它可以在其上工作,甚至访问其私有字段。

于 2013-06-29T13:36:16.790 回答
2

问题

让我们一块一块地看你的代码:

#include <iostream>
#include <string>

using namespace std;

这里只是一个简短的说明:使用using namespace std;.

class C
{
private:
    string str;
    friend void func();
};

这里定义了一个类C,你声明这个类的对象会包含一个字符串,这个字符串是私有的(即只能被类成员和好友访问),你声明全局函数void func()为好友,即允许访问strC和任何类型对象的私有成员(在这种情况下) C。请注意,除了该权限之外,func与 class 没有任何关系C

void func()
{
        str = "Lala";
        cout << str << endl;

}

在这里,您尝试分配一个str您从未声明过的变量。请记住,除了可以访问 type 的私有成员 和对象之外,func与该类没有任何关系。但是,看不到类型的对象,即使有,也没有什么可以告诉编译器要从哪个对象中获取,甚至您正在谈论in 。我会再次记住您,它完全独立于,因此代码的解释方式与不会将其声明为朋友的方式相同。CCCCstrstrCfuncCC

int main()
{
    func();
}

好的,这里没什么特别的,你只是在打电话func

如何修复它

现在,如何修复您的代码?嗯,有几种可能:

供应对象

本地对象

由于是类对象str的成员,因此您需要该类的对象。所以你可以例如做:C

void func()
{
  C object;
  object.str = "Lala";
  std::cout << object.str << std::endl;
}

在这里,您在 中创建一个本地对象,为该对象的func成员分配一个值,然后将其输出。要查看不同的对象具有不同的成员,您可以例如编写: str

void func()
{
  C object1, object2;
  object1.str = "Lala";
  object2.str = "Lele";
  std::cout << object1.str << " -- " << object2.str << "\n";
}

Lala -- Lele是因为第一个对象的str成员具有 value"Lala"而第二个对象的str成员具有 value "Lele"

函数参数

另一种选择是您将对象作为参数传递,例如

void func(C object)
{
  std::cout << object.str << " -- ";
  object.str = "Lele";
  std::cout << object.str << " -- ";
}

int main()
{
  C main_object;
  main_object.str = "Lala";
  func(main_object);
  std::cout << object.str << std::endl;
}

这打印Lala -- Lele -- Lala

这里发生的情况main是创建了一个对象,其str成员被分配了 valeu "Lala"。在调用 时func,会创建该对象的副本,然后您可以从 访问该副本func。由于它是一个副本,它最初还包含与"Lala", whichfunc then outputs. Then the assignment infunc changes thestr member *of that copy* to"Lele" and outputs that. The original object is not affected as the output inmain` 显示的相同的值。

所以你看,可以有几个对象,你说你想访问哪个str对象的成员是至关重要的。

现在,如果您不打算更改被调用函数中的对象,则制作副本只是浪费时间,因此您也可以将其作为对 const 的引用传递

void func(C const& object)
{
  std::cout << object.str << std::endl;
}

int main()
{
  C main_object;
  main_object.str = "Lala";
  func(main_object);
}

参数C const&说“我想直接访问调用者给我的对象,但我保证不会改变它。” “直接访问”部分用 表示&,“我保证不改变它”用 表示const。编译器实际上会检查您是否遵守诺言并且不要尝试更改它(也就是说,如果func您尝试这样做object.str = "Lele",编译器会抱怨(有一些方法可以告诉编译器闭嘴,但您不应该)不要那样做;只要信守诺言)。但是请注意,这再次仅适用于该特定对象;例如,以下代码完全可以:

void func(C const& object)
{
  C another_object;
  another_object.str = "Lele";
  std::cout << object.str << " -- " << another_object.str << std::endl;
}

int main()
{
  C main_object;
  main_object.str = "Lala";
  func(main_object);
}

这不会产生错误并打印Lala -- Lele,因为您再次处理不同的对象。

当然,您可能确实想更改传递给您的对象。然后你可以&不使用const

void func(C& object)
{
  std::cout << object.str << " -- ";
  object.str = "Lele";
  std::cout << object.str << " -- ";
}

int main()
{
  C main_object;
  main_object.str = "Lala";
  func(main_object);
  std::cout << object.str << std::endl;
}

这打印Lala -- Lele -- Lele

现在您再次直接访问作为参数传递的对象 from main,但这一次,您不保证不更改它,实际上您确实更改了它。的输出main表明确实main_object发生了变化。

使变量成为静态成员

现在,您可能真的希望只有一个strin C,而不是每个该类型的对象都有一个单独的。如果您绝对肯定这是您想要的,那么您可以创建str该类的静态成员:

class C
{
private:
  static std::string str; // note the keyword "static" here
  friend void func();
};

std::string C::str; // You have to have an extra definition for class static variables!

现在您可以str在没有C可用对象的情况下访问。但是请注意,您仍然需要告诉内部的编译器func您要访问str内部C

void func()
{
  C::str = "Lala";
  std::cout << C::str << std::endl;
}

您还可以访问对象上的变量,就好像它是该对象的成员一样。但是请注意,这并不意味着不同的对象仍然有自己的str. 例如,随着类定义的改变,我们将得到与上面代码不同的行为:

void func()
{
  C object1, object2;
  object1.str = "Lala";
  object2.str = "Lele";
  std::cout << object1.str << " -- " << object2.str << "\n";
}

现在我们将得到输出Lele -- Lele,因为只有一个str不依赖于对象(object1.str在这种情况下的语法在这方面具有误导性;实际上这里它的意思是“为 的类型str定义的,即”)。object1C

于 2013-06-29T13:58:43.323 回答
2

这不起作用,因为 str 没有在 func() 中定义。你应该有一个 C 的实例。

void func()
{
    C foo;
    foo.str = "Lala";
    cout << str << endl;
}

如果需要,可以将 C 实例作为参数传递:

void func(C &foo)
{
    foo.str = "Lala";
    cout << str << endl;
}
于 2013-06-29T13:35:34.003 回答
1
void func(C* object)
{
        object->str = "Lala";
        cout << object->str << endl;

}

由于func不是该类的成员,因此您不能将其称为object.func(). 因此,该函数将不知道您希望更改哪个类的对象。所以你必须明确地将对象指针传递给函数。使用参考也可以。

或者您可以声明strstatic. 但是静态成员会使类的所有实例共享相同的值。

于 2013-06-29T13:39:46.610 回答