【问题标题】:Variable scope error when declaring friend function声明友元函数时出现变量范围错误
【发布时间】:2011-09-12 07:04:25
【问题描述】:

友元函数不能访问类的变量

我遇到了几个友元函数无法访问它们被声明为友元的类中的变量的问题。

实际的错误文本是: 错误:未在此范围内声明“fid”。这对其他私有变量重复。 对于三个函数,read、negative 和 write,给出了相同的错误。

几点说明: 1)本实验要求我编写代码,以便两个类都可以使用函数。

我正在使用 g++ 在 windows 中使用 code::blocks 编译它,我还尝试使用 -g 标志从终端使用 g++ 在 ubuntu 中编译我的代码,但两次都得到相同的错误。

您的任何建议将不胜感激。

头文件

#ifndef PXMUTILS_H
#define PXMUTILS_H

#include <cstdio>
#include <cstdlib>
#include <string>
#include <sstream>
#include <vector>
#include <iostream>
#include <fstream>
#include <stdio.h>
#include <string.h>

using namespace std;
typedef unsigned char uchar;

class pgm
{
public:
    pgm();
    ~pgm();
    void read(string &);
    void negative();
    void write(string);
    friend void read (const string &);
    friend void write(string);
    friend void negative();
private:
    int nr;
    int nc;
    int mval;
    int ftyp;
    string fid;
    uchar **img;
};

class ppm
{
public:
    ppm();
    ~ppm();
    void read(string &);
    void negative();
    void write(string);
    friend void read (const string &);
    friend void write (string);
    friend void negative ();
private:
    int nr;
    int nc;
    int mval;
    int ftyp;
    string fid;
    uchar **img;
};

#endif

C++程序

#include <cstdio>
#include <cstdlib>
#include <string>
#include <sstream>
#include <vector>
#include <iostream>
#include <fstream>
#include <stdio.h>
#include <string.h>
#include "pxmutils.h"

using namespace std;
typedef unsigned char uchar;

uchar ** newimg(int nr, int nc, int ftyp)
{
uchar **img=new uchar *[nr];
img[0]=new uchar [nr*nc*ftyp];
for(int i=1; i<nr; i++)
    {
        img[i]=img[i-1]+nc*ftyp;
    }
    return img;
}

void deleteimg(uchar **img)
{
    if(img)
    {
        if(img[0])
        {
            delete [] img[0];
        }
        delete [] img;
    }
}
void read (const string &fname)
{
    ifstream fin(fname.c_str(), ios::in);
    if(!fin.is_open())
    {
        cerr<<"Could not open "<<fname<<endl;
        exit(0);
    }
    fin >>fid
        >>nc
        >>nr
        >>mval;
        while (fin.get() != '\n') { /*skip to EOL */ }

    img=newimg(nr, nc);
    fin.read((char *)img[0], nr*nc);
    fin.close();
    }

void set_cmap(string mname)
{
}

void negative()
{
    for(int i=0; i<nr; i++)
    {
        for(int j=0; j<nc; j++)
        {
           int t=img[i][j];
           img[i][j]=(255-t);
        }
    }
}

void write(string fname)
{
        ofstream fout (fname.c_str(), ios::out);
        size_t dp;
    if ((dp = fname.rfind(".pgm")) != string::npos)
        {
            fout<<"P5"<<endl;
        }
        if((dp= fname.rfind(".ppm")) != string::npos)
        {
            fout<<"P6"<<endl;
        }
        fout<<nc<<" "<<nr<<endl;
        fout<<mval<<endl;

    for(int i=0; i <nr; i++)
    { 
        for (int j=0; j<nc; j++)
        {
            fout<<img[i][j]<<" ";
        }
        fout<<endl;
    }

    fout.close();
}

pgm::pgm()
{
    nr=0;
    nc=0;
    mval=0;
    ftyp=1;
    fid="";
    img=NULL;
}

pgm::~pgm()
{
    deleteimg(img);
}

ppm::ppm()
{
    nr=0;
    nc=0;
    mval=0;
    ftyp=1;
    fid="";
    img=NULL;
}

ppm::~ppm()
{
    deleteimg(img);
}

功能测试程序

#include <cstdlib>
#include <iostream>
#include <string>
using namespace std;

#include "pxmutils.h"

int main(int argc, char *argv[])
{
    if (argc == 1) {
        cerr << "No input file specified!\n";
        exit(0);
    }

    string fname = argv[1];
    size_t dp;

    if ((dp = fname.rfind(".pgm")) == string::npos) {
        cout << "PGM error: file suffix " << fname
             << " not recognized\n";
        exit(0);
    }

    fname.erase(dp);

pgm img_g;
    ppm img_c;

    img_g.read(fname+".pgm");

    if (argc == 3)    
    img_c.set_cmap(argv[2]);

    img_c = img_g;

    img_g.negative();

    img_g.write(fname+"_n.pgm");
    img_c.write(fname+"_c.ppm");
}

【问题讨论】:

  • 字太多,代码太多,能不能缩小一点?
  • 看起来您只想在类声明之外定义实例方法。那里不需要朋友
  • 另外:如果这是家庭作业 - 请标记它。

标签: c++ gcc scope friend-function


【解决方案1】:
fin >>fid
    >>nc
    >>nr
    >>mval;
    while (fin.get() != '\n') { /*skip to EOL */ }

在此代码中,fid、nc、nr 等未定义。您需要使用类实例才能访问它们,它们本身并不存在。

您的函数不接受类对象作为参数,那么您将如何读取它们?

【讨论】:

  • 抱歉,应该发布第三个文件,即实际使用类的文件。
【解决方案2】:

您应该重新考虑您的设计。如果可能的话最好避免使用friend函数,

【讨论】:

  • 我会使用什么设计来避免使用友元函数?
  • OOP 的思想是你有一个类并提供一个公共接口。然后,您可以更改底层代码,只要公共接口保持不变 - 您的代码就可以工作。朋友函数打破了这个概念。 (参见 Effective C++ 第 2 版 - Scott Myers)
【解决方案3】:

您需要回归基础。当您定义类的非静态成员时,您正在定义类对象的 attributesoperations,但这些属性本身并不存在,仅作为一部分类的实例。

这个概念与 accessaccess specifiers 是正交的,也就是说,无论成员是 publicprotected 还是 private,都是如此。一旦你有了一个实例,当你尝试访问这些成员时,访问说明符开始发挥作用,友谊开始发挥作用:它将授予你的代码访问权限否则将无法访问的成员(privateprotected 在继承层次结构之外)。

您的代码中的问题是您没有对象,因此无法访问该对象的成员。您将需要创建或将适当类型的对象传递给函数。

代码中还有其他问题,例如,newimg 内部的内存分配看起来有点可疑(您打算分配什么?)但这超出了本问题的范围。

【讨论】:

    猜你喜欢
    • 2020-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-08
    相关资源
    最近更新 更多