各位大牛,调用类中private变量下的数组,编译时说是 [Linker error] undefined reference to 这个数组,是怎么回事啊?

唐朝书生 发布于 2012/03/17 21:48
阅读 607
收藏 0
各位大牛,调用类中private变量下的数组,编译时说是 [Linker error] undefined reference to 这个数组,是怎么回事啊?
例如在temp = temp - key[j] + 26;里用到了private变量key[j]数组,但是编译一下,提示是没有定义到这个数组的链接([Linker error] undefined reference to `Vigenere::key' )
请问这个问题怎么解决?
谢谢各位

源代码如下:
#include<conio.h>
#include<fstream>
#include<iostream>
using namespace std;
class Vigenere
{
  public:
  Vigenere();
  ~Vigenere();
  void Encrypt();//加密函数 ,将里面的英文字符进行加密  
  void Decipher();//解密函数   
  private:
  static int key[5];  
    
};
Vigenere::Vigenere()//构造函数  
{
  int key[5] = {19,7,8,13,10};//密钥   
}
Vigenere::~Vigenere()//析构函数  
{
}
void Vigenere::Encrypt()
{
    
  fstream infile,outfile;
  infile.open("a.txt",ios::in);//读取明文文件  
  if(!infile)
  {
  cout<<"无法打开明文文件a.txt"<<endl;
  abort();
  }
  outfile.open("b.txt",ios::out);
  if(!outfile)
  {
  cout<<"无法打开密文文件b.txt"<<endl;
  abort();
  }
  char ch;//用来存放从文件里取出的字符  
  int temp;//用来存放从文件里取出的字符转化为的数,(a或A对应数字0,b或B对应数字1,……)  
  int i = 0;//用来标记数组k[i]的下标  
  while(infile.get(ch))
  {
  if(ch >= 'A'&&ch <= 'Z')
  {
  temp = (int)ch - 65;//将字母转化为对应的数字 ,(a或A对应数字0,b或B对应数字1,……)  
  temp = (temp * 13 + key[i]) % 26 + 65;//加密算法为先乘以13,在加上key[i]的值,然后模26,加65是将其转换为字母所对应的字符  
  ch = (char)temp;//转换为字符  
  outfile.put(ch);//将加密后的字符赋值到目标文件里  
  i = (i + 1)%5;//使k[1]下标在0到4之间循环  
  }else if(ch >= 'a'&&ch <= 'z')
  {
  temp = (int)ch - 97;
  temp = (temp * 13 + key[i]) % 26 + 97;
  ch = (char)temp;
  outfile.put(ch);
  i = (i + 1)%5;
  }else//如果不是英文字符的话  
  outfile.put(ch);//保持源字符不变  
  }
  infile.close();//关闭源文件  
  outfile.close();//关闭目标文件  
}
void Vigenere::Decipher()//解密  
{
  fstream infile,outfile;
  infile.open("b.txt",ios::in);
  if(!infile)
  {
  cout<<"无法打开密文文件b.txt"<<endl;
  abort();
  }
  outfile.open("c.txt",ios::out);
  if(!outfile)
  {
  cout<<"无法打开明文文件c.txt"<<endl;
  abort();
  }
  char ch;//用来存放从文件里取出的字符  
  int temp;//用来存放从文件里取出的字符转化为的数,(a或A对应数字0,b或B对应数字1,……)  
  int j = 0;//用来标记数组key[j]的下标  
  int n = 1;//用来标记所乘的13的倍数  
  while(infile.get(ch))
  {   
  if(ch >= 'A'&&ch <= 'Z')
  {
  temp = (int)ch - 65;//将字母转化为对应的数字 ,(a或A对应数字0,b或B对应数字1,……)
  //解密  
  temp = temp - key[j] + 26;
  //加密是按照原数乘以13在加上key[i],然后模26的到的  
  //解密的话是先减去key[j]再加上26(在加上26的目的是为了防止出现负数)
  while(temp % 13 != 0)
  {
  temp = temp + n * 26;
  n++;
  }
  temp = temp / 13;
  // 再加上n倍的26,最后然后除13取余看是否能够除尽,能除尽的最小数就是所要求的数  
  ch = (char)temp;//转换为字符  
  outfile.put(ch);//将解密密后的字符赋值到目标文件里  
  j = (j + 1)%5;//使key[1]下标在0到4之间循环  
  }else if(ch >= 'a'&&ch <= 'z')
  {
  temp = (int)ch - 65;//将字母转化为对应的数字 ,(a或A对应数字0,b或B对应数字1,……)
  //解密  
  temp = temp - key[j] + 26;
  //加密是按照原数乘以13在加上key[i],然后模26的到的  
  //解密的话是先减去key[j]再加上26(在加上26的目的是为了防止出现负数)
  while(temp % 13 != 0)
  {
  temp = temp + n * 26;
  n++;
  }
  temp = temp / 13;
  // 再加上n倍的26,最后然后除13取余看是否能够除尽,能除尽的最小数就是所要求的数  
  ch = (char)temp;//转换为字符  
  outfile.put(ch);//将解密密后的字符赋值到目标文件里  
  j = (j + 1)%5;//使key[j]下标在0到4之间循环  
    
  }else//如果不是英文字符的话  
  outfile.put(ch);//保持源字符不变  
  }
  infile.close();//关闭源文件  
  outfile.close();//关闭目标文件  
}
int main()
{
  Vigenere vigenere;
  vigenere.Encrypt();//加密  
  vigenere.Decipher();//解密  
  system("pause");
  return 0;
} 
编译之后出现如下提示:
  [Linker error] undefined reference to `Vigenere::key'
加载中
0
leo108
leo108
Vigenere::Vigenere()//构造函数   

  int key[5] = {19,7,8,13,10};//密钥    

这里明显不对……

key已经在上面定义过了,你在这里定义并赋值没有任何作用,因为构造函数执行完毕这几个就销毁了

0
唐朝书生
唐朝书生

引用来自“leo108”的答案

Vigenere::Vigenere()//构造函数   

  int key[5] = {19,7,8,13,10};//密钥    

这里明显不对……

key已经在上面定义过了,你在这里定义并赋值没有任何作用,因为构造函数执行完毕这几个就销毁了

我把int Vigenere::key[5] = {19,7,8,13,10};
放在了构造函数之外,然后编译一下之后可以了。
代码如下:
class Vigenere
{
      public:
             Vigenere();
             ~Vigenere();
             void Encrypt();//加密函数 ,将里面的英文字符进行加密 
             void Decipher();//解密函数  
      private:
              static int key[5]; 
               
};
int Vigenere::key[5] = {19,7,8,13,10};
Vigenere::Vigenere()//构造函数 
{
       //int key[5] = {19,7,8,13,10};//密钥            
}
Vigenere::~Vigenere()//析构函数 
{
}
请问如何能在构造函数里面初始化该数组,是把数组的静态定义static去掉吗?
0
leo108
leo108

引用来自“李正东”的答案

引用来自“leo108”的答案

Vigenere::Vigenere()//构造函数   

  int key[5] = {19,7,8,13,10};//密钥    

这里明显不对……

key已经在上面定义过了,你在这里定义并赋值没有任何作用,因为构造函数执行完毕这几个就销毁了

我把int Vigenere::key[5] = {19,7,8,13,10};
放在了构造函数之外,然后编译一下之后可以了。
代码如下:
class Vigenere
{
      public:
             Vigenere();
             ~Vigenere();
             void Encrypt();//加密函数 ,将里面的英文字符进行加密 
             void Decipher();//解密函数  
      private:
              static int key[5]; 
               
};
int Vigenere::key[5] = {19,7,8,13,10};
Vigenere::Vigenere()//构造函数 
{
       //int key[5] = {19,7,8,13,10};//密钥            
}
Vigenere::~Vigenere()//析构函数 
{
}
请问如何能在构造函数里面初始化该数组,是把数组的静态定义static去掉吗?
Vigenere::Vigenere()//构造函数 
{
       key[0] = 19;
       key[1] = 7;
       key[2] = 8;
       key[3] =13;
       key[4] = 10;
}
0
唐朝书生
唐朝书生

引用来自“leo108”的答案

引用来自“李正东”的答案

引用来自“leo108”的答案

Vigenere::Vigenere()//构造函数   

  int key[5] = {19,7,8,13,10};//密钥    

这里明显不对……

key已经在上面定义过了,你在这里定义并赋值没有任何作用,因为构造函数执行完毕这几个就销毁了

我把int Vigenere::key[5] = {19,7,8,13,10};
放在了构造函数之外,然后编译一下之后可以了。
代码如下:
class Vigenere
{
      public:
             Vigenere();
             ~Vigenere();
             void Encrypt();//加密函数 ,将里面的英文字符进行加密 
             void Decipher();//解密函数  
      private:
              static int key[5]; 
               
};
int Vigenere::key[5] = {19,7,8,13,10};
Vigenere::Vigenere()//构造函数 
{
       //int key[5] = {19,7,8,13,10};//密钥            
}
Vigenere::~Vigenere()//析构函数 
{
}
请问如何能在构造函数里面初始化该数组,是把数组的静态定义static去掉吗?
Vigenere::Vigenere()//构造函数 
{
       key[0] = 19;
       key[1] = 7;
       key[2] = 8;
       key[3] =13;
       key[4] = 10;
}

如果是去掉了private下key[i]的static标签,编译能够通过,代码如下:

class Vigenere

{

      public:

             Vigenere();

             ~Vigenere();

             void Encrypt();//加密函数 ,将里面的英文字符进行加密 

             void Decipher();//解密函数  

      private:

              int key[5]; 

               

};

//int Vigenere::key[5] = {19,7,8,13,10};

Vigenere::Vigenere()//构造函数 

{

       //int key[5] = {19,7,8,13,10};//密钥    

       key[0] = 19;

       key[1] = 7;

       key[2] = 8;

       key[3] =13;

       key[4] = 10;        

}

如果没有去掉private下key[i]的static标签,编译还是会出现  [Linker error] undefined reference to `Vigenere::key' 

代码如下:

class Vigenere

{

      public:

             Vigenere();

             ~Vigenere();

             void Encrypt();//加密函数 ,将里面的英文字符进行加密 

             void Decipher();//解密函数  

      private:

             static int key[5]; 

               

};

//int Vigenere::key[5] = {19,7,8,13,10};

Vigenere::Vigenere()//构造函数 

{

       //int key[5] = {19,7,8,13,10};//密钥    

       key[0] = 19;

       key[1] = 7;

       key[2] = 8;

       key[3] =13;

       key[4] = 10;        

}

 

如果像在第一次构造后就保持key[i]不变,需不需要要在private下面加static,怎样修改才能达到这样呢?

leo108
leo108
static不是这种用途……多看看书吧……
0
中山野鬼
中山野鬼

引用来自“leo108”的答案

Vigenere::Vigenere()//构造函数   

  int key[5] = {19,7,8,13,10};//密钥    

这里明显不对……

key已经在上面定义过了,你在这里定义并赋值没有任何作用,因为构造函数执行完毕这几个就销毁了

这个是正解。
0
中山野鬼
中山野鬼

引用来自“李正东”的答案

引用来自“leo108”的答案

Vigenere::Vigenere()//构造函数   

  int key[5] = {19,7,8,13,10};//密钥    

这里明显不对……

key已经在上面定义过了,你在这里定义并赋值没有任何作用,因为构造函数执行完毕这几个就销毁了

我把int Vigenere::key[5] = {19,7,8,13,10};
放在了构造函数之外,然后编译一下之后可以了。
代码如下:
class Vigenere
{
      public:
             Vigenere();
             ~Vigenere();
             void Encrypt();//加密函数 ,将里面的英文字符进行加密 
             void Decipher();//解密函数  
      private:
              static int key[5]; 
               
};
int Vigenere::key[5] = {19,7,8,13,10};
Vigenere::Vigenere()//构造函数 
{
       //int key[5] = {19,7,8,13,10};//密钥            
}
Vigenere::~Vigenere()//析构函数 
{
}
请问如何能在构造函数里面初始化该数组,是把数组的静态定义static去掉吗?
你这两个不同的写法完全是两个不同的操作对象。前面错误的操作是对一个方法中的临时变量进行赋值,后面是类的成员变量进行定义。如果我没记错的话,你后面一种写法是保证每个类的实体,都用此唯一的空间。这是加static的理由。。当然时间久了。我可能说的不对,还望其他朋友给予指正。
0
jackandrose
jackandrose

如果像java那样理解就好了,static变量是属于类的,不是属于对象的。所以构造函数不能对其完成初始化,否则生成很多对象,每个对象都能初始化,那岂不是乱套了。C++的父亲这么规定,static成员只能在类外的某个地方定义,此例中是int Vigenere::key[5] = {19, 7,8, 13,10}。当然现在的最新的C++版本可能会支持直接在类内部初始化,不过也说不准,不过我觉得static const应该会支持的。

返回顶部
顶部