zoukankan      html  css  js  c++  java
  • static和 friend友元 的一点调试体验

      本篇日志是作为菜鸟C++学员,写的一篇调试错误的过程,旨在记录自己的学习过程,帮助自己提高,后面附有我的代码。

      今天早上在看Essential C++ P125时,想照着书上的例子写一次,看看运行结果。 结果当我抄书上的代码时,一直从书第四章开头找到了P125,原因是书上是按照函数过程这么讲的,造成我抄完代码也不知所以然,结果当然就是编译不通过了。

      第一个问题:

      当时第一次出现的错误是LNK2001,好像是这个编号,然后我就试,看是不是这里的问题,改一次编译一次,当然这样是没有结果的。最后我想到了百度,百度以后,得到的结果是声明的变量在另一个文件里面找不到。 也就是说这时候才找到问题原因是 class Triangular类中的private 变量 static std::vector<int> _elems在class Triangular里找不到。然后我就改这个问题,第一次是这样改的:在class Triangular的cpp里加上代码 extern _elems;第二次改成extern std::vector<int> _elems; 然后第三次改成std::vector<int> Triangular::_elems; 这时候这个问题才算解决。

      收获:

      之前看过C++ primer,也看过关于声明,定义这些问题,但之前都只是看书,没有体会,也更没有“一个文件里声明,另一个文件里定义”的这种体会,这次也重新回忆了一下static变量声明时,默认是有extern的,也又学习了一次extern声明和变量定义,还看到了一次一个文件里声明变量,在另一个文件里定义的情况(这里是在.h文件声明一个class的全局vector,在class的cpp文件里定义改vector)

     

      第二个问题:

      改完第一个问题后,又出现了第二个问题,在类BaseIterator里重载的operator*() 一直出错,错误类似于上述情况,都是链接时出错。当时情况是抄的书上的代码,一报错,不知道该从哪里下手,然后就找自己感觉像是错的地方,改啊改,还是报错(主要问题是Triangular和BaseIterator里互相调用对方的成员变量,我就这里加一个.h文件,继续报错;那里加一个.h,仍然报错;这里加一个class声明,报错;一直试了好长时间)。最后看着抄的一堆代码,想起了上午调试static变量的过程(调试第一个问题的过程就是单独抛开书上的这个例子,单独建了两个简单的类来做的),重新建了一个工程,然后写一个重载函数,编译一个(主要重载的就是++,这里没有调试*),最后这个测试程序运行正确。然后我就把之前抄的代码里面所有不相干的代码都注视起来,擦,还是报错。。然后,我想了个绝招,,我照着这个测试程序,把抄的程序一行一行注释起来,唯独没有改变类的名字,结果:依然报错。。这次我也不知道问题是哪了。没办法,我就重新建了一个工程EssentialCppP125Again,按照我自己的需要,先写BaseIterator这个类,写一个重载函数,编译一次,,最后成功写到了重载*函数,见到这个*我有点害怕,因为它牵扯到Triangular 类。而Triangular类之前上午写的时候就因为那个static成员变量搞了一上午。所以我就抛开课本上这个Triangular类的定义,只写自己需要的变量和函数(对于课本上的一些测试越界的函数,还有一些赋值等等的函数都省略了)。最后终于调试到了要写*的地方。Triangular类里声明友元函数 friend int BaseIterator::operator*(); 类BaseIterator里定义,又是这个A引用B,B引用A的问题,一下午就被这个问题整过去了,在群里也问了问,群友的回答是:加class Triangular;class BaseIterator;声明和引入对方对象的指针,代码如下:

    TestPointer
     1 #include<iostream>
    2 using namespace std;
    3 class A;
    4 class B;
    5
    6 class A
    7 {
    8 public:
    9 B *bb;
    10 static int sta;
    11 };
    12
    13 class B
    14 {
    15 public:
    16 A *aa;
    17 void p(){cout<<A::sta;}
    18 };
    19 int main(){
    20
    21 return 0;
    22 }
    
    

      这个,我还没有测试,先继续我最后的解决方法。我最后是在class BaseIterator里include Triangular.h,全部代码如下:(但这里我还是不懂为什么这样就可以通过,不懂事怎么互相引用的):(按照写的过程贴出所有代码)

    1、BaseIterator类

      1.1 BaseIterator.h

    BaseIterator.h
     1 #pragma once
    2 #include <iostream>
    3 #include <vector>
    4
    5
    6
    7
    8 class BaseIterator
    9 {
    10 public:
    11 BaseIterator(void);
    12 ~BaseIterator(void);
    13 public:
    14 BaseIterator(int index) : _index(index) {}
    15 bool operator==(const BaseIterator& rhs) {return _index == rhs._index;}
    16 bool operator!=(const BaseIterator& rhs) {return !(*this == rhs);}
    17 BaseIterator& operator++();
    18 BaseIterator operator++(int);
    19 int operator*();
    20
    21 int index() {return _index;}
    22
    23 private:
    24 int _index;
    25 };
    
    

      1.2 BaseIterator.cpp

    BaseIterator.cpp
     1 #include "StdAfx.h"
    2 #include "BaseIterator.h"
    3 #include "Triangular.h"
    4
    5
    6 //std::vector<int> Triangular::_elems;
    7 BaseIterator::BaseIterator(void)
    8 {
    9 _index = 0;
    10 }
    11
    12 BaseIterator::~BaseIterator(void)
    13 {
    14 }
    15
    16
    17 BaseIterator& BaseIterator::operator++()
    18 {
    19 ++_index;
    20 return *this;
    21 }
    22
    23 BaseIterator BaseIterator::operator++(int)
    24 {
    25 BaseIterator tmp = *this;
    26 ++_index;
    27 return tmp;
    28 }
    29
    30 int BaseIterator::operator*()
    31 {
    32 return Triangular::_elems[this->index()];
    33 }

    2 Triangular类

      2.1 Triangular.h

    Triangular.h
     1 #pragma once
    2 #include <vector>
    3 #include "BaseIterator.h"
    4 class Triangular
    5 {
    6 public:
    7 typedef BaseIterator iterator;
    8
    9 public:
    10 Triangular(void);
    11 ~Triangular(void);
    12
    13 public:
    14 Triangular(int len);
    15 int length() const { return _length;}
    16 int elem(int pos) const { return _elems[pos] ;}
    17
    18 static void gen_elements(std::vector<int>::size_type length);
    19
    20 BaseIterator Triangular::begin();
    21 BaseIterator Triangular::end();
    22 friend int BaseIterator::operator*();
    23
    24 private:
    25 int _length;
    26
    27 const static int _max_elems = 1024;
    28 static std::vector<int> _elems;
    29 };

      2.2Triangular.cpp

    Triangular.cpp
     1 #include "StdAfx.h"
    2 #include "Triangular.h"
    3 #include <iostream>
    4
    5 std::vector<int> Triangular::_elems;
    6
    7 Triangular::Triangular(void)
    8 {
    9 _length = 0;
    10 }
    11
    12 Triangular::Triangular(int len)
    13 {
    14 _length = len >= 0 ? len : 0;
    15
    16 std::vector<int>::size_type elem_cnt = _length;
    17
    18 if ( _elems.size() < elem_cnt )
    19 {
    20 gen_elements(elem_cnt);
    21
    22 }
    23 }
    24
    25 Triangular::~Triangular(void)
    26 {
    27 }
    28
    29 BaseIterator Triangular::begin()
    30 {
    31 return BaseIterator(0);
    32 }
    33
    34 BaseIterator Triangular::end()
    35 {
    36 return _length > 0 ? BaseIterator(_length) : 0;
    37 }
    38
    39 void Triangular::gen_elements(std::vector<int>::size_type length)
    40 {
    41 if (length < 0 || length > _max_elems)
    42 {
    43 std::cerr << "length < 0 or length > _max_elems" << std::endl;
    44 exit(-1);
    45 }
    46 if (_elems.size() < length)
    47 {
    48 int ix = _elems.size();
    49 for (; ix < length; ++ix)
    50 {
    51 _elems.push_back(ix*(ix+1)/2);
    52 }
    53 }
    54 }

    3、 main函数测试

    main
     1 // EssentialCppP122Again.cpp : 定义控制台应用程序的入口点。
    2 //
    3
    4 #include "stdafx.h"
    5 #include "BaseIterator.h"
    6
    7 #include <iostream>
    8 #include "Triangular.h"
    9 using namespace std;
    10
    11
    12 int _tmain(int argc, _TCHAR* argv[])
    13 {
    14 /*BaseIterator iter1;
    15 BaseIterator iter2(1);
    16
    17 ++iter1;*/
    18
    19
    20 Triangular tri(20);
    21 Triangular::iterator iter1 = tri.begin();
    22 Triangular::iterator iter2 = tri.end();
    23 cout << "Triangular Series of " << tri.length() << " elements\n";
    24 while (iter1 != iter2)
    25 {
    26 //cout << *iter1 << '\t' ;
    27 cout << tri.elem(iter1.index()) << '\t';
    28 ++iter1;
    29 }
    30 cout << endl;
    31
    32
    33 return 0;
    34 }

    收获:

      以后尽量少抄书上的代码,要在觉得自己理解的差不多以后,按照自己的想法来写出来,而不是当码字员。还有就是这样能按照逻辑过程来写代码,而不是按照书上的页码来抄代码。还有测试的时候不要把书上的所有代码功能都实现,当然这个现在也不好定,如果一直不按照规范,注意自己代码的边界检查,等等这些,可能会影响自己的习惯,但如果这样写了又可能紧紧只是一个看结果的过程而浪费很多时间。。尽量按照书上那样写完整吧,这点现在还不好体会,没法总结。

    PS:Triangular类和书上的要实现的目的相差很大,我这里只是为了测试重载*,所以不是按照书上定义_elems,_beg_pos等等这些变量来写的程序。

     

    总结:

      这次测试到此结束,但问题依然还在,就是上面说的友元和互相#include "XXX.h"的问题(红色部分),这个问题先暂时遗留在这里,等后面再看到这方面知识时再回头体会,如哪位朋友正好方便告诉我这个问题的解答,还麻烦能回帖给说下书名页码或者网址链接,先谢谢各位兄弟姐妹。

  • 相关阅读:
    把握人生12种财富:让商人更自信
    英语谚语的汉译
    心胸有多大,事业才可能有多大
    想成领袖?先瞄准老板身边的位置
    绝对挑战:如何来提高自己的影响力?
    送给创业的朋友:落入坑洞的猎人
    跨越危机,塑造完美的职业生涯(三)
    如果一个男人真的爱你
    跨越危机,塑造完美的职业生涯(一)
    来自最伟大推销员的成功金句
  • 原文地址:https://www.cnblogs.com/ziyoudefeng/p/2405082.html
Copyright © 2011-2022 走看看