Comments (10)
我按照你给的代码在vs2015上,在clear函数体内的s.contents,s.height , s.width,编译器会显示警告不可访问。
你是不是少写了 friend void Window_mgr::clear(ScreenIndex);
不知道是什么问题。难道是编译器的问题?
我测试了一下,在 VS 2015 上,ex7.32 并没有什么问题。
from cppprimer.
我是直接复制粘贴代码的,提示是这样的
严重性 代码 说明 项目 文件 行
错误(活动) 成员 "Screen::contents" (已声明 所在行数:54) 不可访问 ConsoleApplication11 c:\Users\Administrator.0KMF4QN6XAERFK5\Documents\Visual Studio 2015\Projects\ConsoleApplication11\ConsoleApplication11\标头.h 61
from cppprimer.
我是直接复制粘贴代码的,提示是这样的
那请你贴出完整的代码,答案里只有头文件,您的 main 函数是怎样的呢?
from cppprimer.
@pezy 前辈你好。正好也做到了这一题,你的代码在vs2015也编译通过。
但是有一个问题能否麻烦简单解答一下?如果 Window_mgr 类和 Screen 类在两个头文件中,相应的代码应如何设计?我自己搞了半天没搞出来,能否简单提示下,谢谢!
from cppprimer.
@why2cs Window_mgr
类的头文件中,仅需要用到 Screen
类的前置声明即可。
window_mgr.h
#pragma once
#include <vector>
class Screen;
class Window_mgr {
public:
using ScreenIndex = std::vector<Screen>::size_type;
inline void clear(ScreenIndex);
private:
std::vector<Screen> screens;
};
window_mgr.cpp
#include "window_mgr.h"
#include "screen.h"
inline void Window_mgr::clear(ScreenIndex i)
{
if (i >= screens.size()) return; // judge for out_of_range.
Screen& s = screens[i];
s.contents = std::string(s.height * s.width, ' ');
}
screen.h
#pragma once
#include <vector>
#include <string>
#include <iostream>
#include "window_mgr.h"
class Screen {
friend void Window_mgr::clear(ScreenIndex);
public:
using pos = std::string::size_type;
Screen() = default; // 1
Screen(pos ht, pos wd) : height(ht), width(wd), contents(ht * wd, ' ') {} // 2
Screen(pos ht, pos wd, char c) : height(ht), width(wd), contents(ht * wd, c){} // 3
char get() const { return contents[cursor]; }
char get(pos r, pos c) const { return contents[r * width + c]; }
inline Screen& move(pos r, pos c);
inline Screen& set(char c);
inline Screen& set(pos r, pos c, char ch);
const Screen& display(std::ostream& os) const
{
do_display(os);
return *this;
}
Screen& display(std::ostream& os)
{
do_display(os);
return *this;
}
private:
void do_display(std::ostream& os) const { os << contents; }
private:
pos cursor = 0;
pos height = 0, width = 0;
std::string contents;
};
inline Screen& Screen::move(pos r, pos c)
{
cursor = r * width + c;
return *this;
}
inline Screen& Screen::set(char c)
{
contents[cursor] = c;
return *this;
}
inline Screen& Screen::set(pos r, pos c, char ch)
{
contents[r * width + c] = ch;
return *this;
}
from cppprimer.
谢谢啦!我发现我的问题出在哪了。
在之前的练习中,我将Window_mgr.h头文件中包含了Screen.h,接着在Window_mgr做了一个类内初始值。如下:
std::vector<Screen> screens{Screen(5,5,'X')};
然后在做这个练习的时候,因为要在Screen类中友元声明Window_mgr::clear,导致:
1.Window_mgr头文件包含有#include "Screen.h",并含有Screen类的前置声明(此时前置声明已无意义)。
2.Screen头文件中包含有#include "Window_mgr.h"
编译时出现问题。麻烦问一下:
1.如果一定要实现screens的类内初始值的话,该怎样做呢?还是根本就不能这样?
2.你的clear函数定义在cpp文件中,如果要定义在Window_mgr.h中,该怎么做呢?
第一次用github,也不太会提问和编辑,谢谢啦。
from cppprimer.
前置声明,是告诉编译器,我这里仅仅只会用到某类的声明,而非定义。
include 头文件是将整个类的定义包含了进来。
如果一定要实现screens的类内初始值的话,该怎样做呢?还是根本就不能这样?
初始化,与声明不同,是必须包含整个类定义的。所以一定要实现的话,你就得 #include "screen.h"
;然而在 Screen
类中,又用到了 Window_mgr
的友元函数,这个也是一定要包含整个类定义的,也必须要 #include "window_mgr.h"
这样互相包含,就成了死局,编译器自然就要报错了。所以结论是,没办法这么做。
你的clear函数定义在cpp文件中,如果要定义在Window_mgr.h中,该怎么做呢?
和上面讲的一样,clear
函数中,需要用到 Screen
类的定义,所以引入 "screen.h" 是必须的,如果你非要定义在 Window_mgr 中,则又会出现上面描述过的那种死局。我将定义分离到 cpp 里,就是为了避免这样的死局。所以结论依然是,没有办法这么做。
from cppprimer.
好的,非常感谢 @pezy 的耐心回答,这个问题解决掉啦!
from cppprimer.
我没有写相应的程序代码,刚试着写了一下不太会写,大神能不能贴一下你的代码让我参考学习一下。
from cppprimer.
我没有写相应的程序代码,刚试着写了一下不太会写
不明白您不会写什么,个人建议您再好好看看书吧。
from cppprimer.
Related Issues (20)
- ex16_29 include error file,It compile failed HOT 2
- about 16.2.7 HOT 2
- Exercise 7.36
- Exercise 6.53
- Exercise 5.3 correct answer HOT 1
- Ex 6_8 HOT 1
- Ex 6_9 (added #include "fact.cpp")
- Ex 6_10 (added "return 0;")
- Exercise 13.37
- Answer to Exercises 3.37 is not entirely true.
- Ex16.49
- The new soulution of Exercise 5.12
- Ex.7.53 will not compile under the C++14 standard
- #include<exception>
- ex7_22.h 'class' instead of 'struct'
- Bug report exercise 16.12
- An error in exercise 16.28, in file <unique_pointer.h>
- Small modification for answer of Exercise 3.9 - mention `s` is a empty string
- Exercise 9.28(The loop may not stop)
- terminate called after throwing an instance of 'std::bad_alloc
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from cppprimer.