小编Pap*_*ter的帖子

如何声明两个类,使A有B和B的成员将A的成员标记为朋友?

我试图从C++ Primer第5版开始练习7.32.该练习要求如下:

定义你自己的版本Screen,并Window_mgr在其中clear的成员Window_mgr和朋友Screen.

下面是定义Screen,Window_mgrclear在文中给出.

class Screen
{
  public:
    using pos = std::string::size_type;
    Screen(pos ht, pos wd, char c) : height(ht), width(wd), contents(ht * wd, c) { }
  private:
    pos height = 0, width = 0;
    std::string contents;
};

class Window_mgr
{
  public:
    using ScreenIndex = std::vector<Screen>::size_type;
    void clear(ScreenIndex);
  private:
    std::vector<Screen> screens{Screen(24, 80 ' ')};
};

void Window_mgr::clear(ScreenIndex i)
{
  Screen &s = screens[i];
  s.contents …
Run Code Online (Sandbox Code Playgroud)

c++ class friend forward-declaration

6
推荐指数
1
解决办法
519
查看次数

理解封装有很多困难

我只是......我不完全确定我理解封装.也许这可能与我仍然在课堂上学习编程而没有制作任何像其他人使用的.REAL世界程序这一事实有关,但我只是不明白它想要完成什么.我理解它限制访问某些类的成员和函数.但是喜欢......从谁那里限制它?我已经看到了几个他们有私有数据成员的例子,但他们有公共的get或set方法,无论如何都可以操作数据成员.那么有什么限制或隐藏的东西呢?

我的书说如下:

"封装提供了两个重要优势:

  1. 用户代码不会无意中破坏封装对象的状态.
  2. 封装类的实现可以随着时间的推移而改变,而无需更改用户级代码."

我想我对他们使用的单词感到困惑.用户代码如何可能破坏对象的状态,或者有人能给我一个例子吗?

我知道我的问题到处都是,但在考虑封装时我的想法也是如此,所以我很难将所有关于它的想法都包含在内(..lol)

c++ encapsulation

6
推荐指数
1
解决办法
345
查看次数

可恢复功能限制背后的基本原理

在关于可恢复功能的文章中,在关于限制的部分中列出了三个限制:

  • 可恢复的函数不能使用可变数量的参数.对于需要varargs的情况,可以将参数展开放在一个函数中,该函数在执行参数展开后调用可恢复函数.
  • 可恢复功能的返回类型必须是future<T>shared_future<T>.对T的限制std::future由此提议定义,但T必须是可复制或可移动的类型,或' void'.还必须能够构造一个T没有参数的变量; 也就是说,如果它是类类型,它必须具有可访问(隐式或显式)默认构造函数.
  • Await表达式可能不会出现在异常处理程序的主体内,并且在执行线程持有任何类型的锁时不应执行.

这种限制背后必然有一个原因,由于我对并发性缺乏了解,我无法推断出原因是什么.有人可以为我这个话题加油吗?

可变数量的参数

这个限制是指C风格的可变参数函数还是C++ 11可变参数模板?

  • 如果是C风格的,限制的原因与宏所做的神奇诡计有关va_*吗?
  • 如果指的是variadric模板函数,我认为限制必须与参数包的解包有关,而不是函数是模板的事实(没有关于模板可恢复函数的措辞,所以我假设它们是法律).

在这两种情况下,我认为编译器可以足够聪明地推断出要使用的功能.

默认的可构造和可复制/可移动类型

我理解返回a std::future或者背后的原因std::shared_future,但我猜测可用类型背后的限制的原因与期货可以使用的类型有关.

因此,本文建议使用两个新的关键字(可恢复和等待)来扩展语言,这两个关键字提供可恢复函数的行为,但最终它信任现有的构造,以在函数和调用者之间传递可恢复函数的返回值.

为什么不为返回值提出某种语言扩展呢?可能(可能)释放对默认可构造和可复制/可移动类型的限制,并修复返回类型和返回类型之间的分配:

因此应该注意到,函数从外部(调用者)和内部观察到的行为之间存在不对称性:外部透视图是函数future<T>在第一个暂停点返回类型的值,而内部透视图是函数T通过return语句返回一个type类型的值(...)

没有等待的异常处理程序,也没有等待锁定的线程

我想在捕获异常时等待某些东西没有任何意义,但我对锁定线程的限制没有任何线索.

c++ resume c++14

6
推荐指数
1
解决办法
172
查看次数

如何使用template-tempate参数专门化模板

最后编辑

我有一个模板的功能:

template <template <typename ...> class P, typename ... Args>
void f(const P<Args...> &p)
{
    std::cout << "Template with " << sizeof...(Args) << " parameters!\n";
}
Run Code Online (Sandbox Code Playgroud)

它到目前为止我测试的任何模板都很好用:

f(std::valarray<int>{});    // Prints: "Template with 1 parameters!"
f(std::pair<char, char>{}); // Prints: "Template with 2 parameters!"
f(std::set<float>{});       // Prints: "Template with 3 parameters!"
f(std::map<int, int>{});    // Prints: "Template with 4 parameters!"
Run Code Online (Sandbox Code Playgroud)

但是,让我们假设我想专门化模板,当它采用带有两个参数的模板时,下面的代码不起作用:

template <>
void f<template <typename, typename> class P, typename A, typename B>(const P<A, B> &p)
{
    std::cout << "Special case!\n";
} …
Run Code Online (Sandbox Code Playgroud)

c++ template-specialization template-templates

6
推荐指数
1
解决办法
228
查看次数

联合的活动成员,统一初始化和构造函数

正如C++标准(工作草案)所说:

9.5.1 [class.union]

在并集中,至多一个非静态数据成员可以在任何时间处于活动状态,也就是说,任何时候最多一个非静态数据成员的值都可以存储在并集中.[...] union的大小足以包含其中最大的非静态数据成员.每个非静态数据成员都被分配,就好像它是结构的唯一成员一样.union对象的所有非静态数据成员都具有相同的地址.

但我不知道如何识别哪个是工会的活跃成员,而且我没有用到足够深入标准来找到标准所说的内容,我试图弄清楚活动成员是如何设置的但我发现它是如何交换的:

9.5.4 [class.union]

[ 注意:通常,必须使用显式析构函数调用和放置新运算符来更改联合的活动成员.- 注完 ] [ 实施例:考虑的对象uunion type U类型的具有非静态数据成员米Mn类型的N.如果M有一个非平凡的析构函数并且N有一个非平凡的构造函数(例如,如果它们声明或继承虚函数),则可以安全地将u的活动成员切换mn使用析构函数和placement new运算符,如下所示:

u.m.~M();
new (&u.n) N;
Run Code Online (Sandbox Code Playgroud)

- 结束例子 ]

所以我的猜测是,工会的活跃成员是首先签署,使用,构建或放置新的成员; 但是这对于统一初始化变得有点棘手,请考虑以下代码:

union Foo
{
    struct {char a,b,c,d;};
    char array[4];
    int integer;
};

Foo f; // default ctor
std::cout << f.a << f.b << f.c << f.d << '\n';
Run Code Online (Sandbox Code Playgroud)

哪个是上面代码的联合的活跃成员?是 …

c++ constructor unions uniform-initialization

6
推荐指数
1
解决办法
750
查看次数

复制和移动构造函数之间的效率差异

C++ 11引入了一个新的rvalue引用概念.我正在某处读它,发现如下:

class Base
{
public:
    Base()  //Default Ctor
    Base(int t)  //Parameterized Ctor

    Base(const Base& b)  //Copy Ctor
    Base(Base&& b)  //Move Ctor
};

void foo(Base b)     //Function 1
{}

void foo(Base& b)   //Function 2
{}

int main()
{
    Base b(10);
    foo(b);        -- Line 1 (i know of ambiquity but lets ignore for understanding purpose)
    foo(Base());   -- Line 2
    foo(2) ;       -- Line 3
}
Run Code Online (Sandbox Code Playgroud)

现在我的理解有限,我的观察结果如下:

  1. 第1行将简单地调用复制构造函数,因为参数是左值.

  2. 在C++ 11之前的第2行会调用复制构造函数和所有那些临时复制内容,但是定义了移动构造函数,这里将调用它.

  3. 第3行将再次调用move构造函数,因为2将隐式转换为Base类型(rvalue).

请纠正并解释上述任何观察结果是否错误.

现在,这是我的问题:

  1. 我知道一旦我们移动一个物体,它的数据就会在呼叫位置丢失.所以,我在上面的例子中如何更改第2行以在foo中移动对象"b"(是否使用std :: move(b)?).

  2. 我读过移动构造函数比复制构造函数更有效.怎么样?我只能想到在移动构造函数的情况下我们在堆上有内存的情况不需要再分配.当我们在堆上没有任何内存时,这个陈述是否成立?

  3. 它是否比通过引用传递更有效(不,对吧?)?

c++ c++11

6
推荐指数
1
解决办法
1782
查看次数

方括号和圆括号操作符,如何选择超载?

我想使用operator[]但是根据索引类型访问一些类数据返回一种数据或其他类型.作为简化示例:

struct S
{
    int   &operator []( int index ) { std::cout << "[i]"; return i_buffer[index]; }
    short &operator [](short index) { std::cout << "[s]"; return s_buffer[index]; }

private:
    int   i_buffer[10]{ 0,  1,   2,   3,   4,   5,   6,   7,   8,   9  };
    short s_buffer[10]{ 0, 111, 222, 333, 444, 555, 666, 777, 888, 999 };
};
Run Code Online (Sandbox Code Playgroud)

没有办法写一个short文字,所以选择short重载的唯一方法是通过强制转换:

S s;
std::cout << s[9] << '\n';        // prints [i]9
std::cout << s[(short)9] << '\n'; // prints …
Run Code Online (Sandbox Code Playgroud)

c++ operator-overloading

6
推荐指数
1
解决办法
437
查看次数

当参数count小于List.Count时,FindLastIndex ArgumentOutOfRangeException

我对C#的问题感到困惑,List下面的代码抛出ArgumentOutOfRangeException:

List<int> l = new List<int>();
l.Add(1); l.Add(1); l.Add(1); l.Add(1); l.Add(1);
l.Add(1); l.Add(1); l.Add(1); l.Add(1); l.Add(1);
l.Add(1); l.Add(1); l.Add(1); l.Add(1); l.Add(1); // 15 elements


//              v <--- From 0
l.FindLastIndex(0, 5, v => v != 1);
//                 ^ <--- up to 5 elements
Run Code Online (Sandbox Code Playgroud)

据我所知,上面的代码,该方法将应用元素0中的lambda,直到它达到5个元素(元素4),但ArgumentOutOfRangeException如果它不能根据我对文档的理解,它会抛出偶数:

ArgumentOutOfRangeException

startIndex超出了有效索引的范围List<T>.

-要么-

count 小于0.

-要么-

startIndex并且count不要在List<T>.中指定有效的部分.

最可能的原因是第三个,但startIndex0(范围内),并count远低于l.Count所以列表内的部分为0〜4,其是有效的.

我做错了什么以及如何解决?

c# list

6
推荐指数
1
解决办法
67
查看次数

如何消除此模板的歧义?

我有一个将大小作为模板参数的类(live demo):

template <std::size_t SIZE> class A
{
    char b[SIZE];
}
Run Code Online (Sandbox Code Playgroud)

它具有用于不同目的的多个构造函数:

using const_buffer_t = const char (&)[SIZE];
using my_type = A<SIZE>;

A()                         : b{} {} // (1) no params
A(const_buffer_t)           : b{} {} // (2) copy contents of given buffer
A(const char * const)       : b{} {} // (3) copy as many items as they fit into the size
explicit A(const my_type &) : b{} {} // (4) copy constructor

// (5) copy as many items as …
Run Code Online (Sandbox Code Playgroud)

c++ templates disambiguation c++11

5
推荐指数
1
解决办法
507
查看次数

Windows窗体设计器,Design> GenerateMember背后的基本原理

在Visual Studio中,在Windows窗体应用程序上工作时,可以在"窗体设计视图"中找到某个选项.我在谈论GenerateMember选项(在Design属性窗口的部分下).

此选项的说明如下:

指示是否将为此组件生成成员变量.

因此,如果我tb1使用Form Dessigner 创建一个文本框到我的表单中f1并将此选项设置为false,则我无法访问代码中的控件(既不存在f1.tb1也不tb1存在).

应该有充分的理由这样做,但我不知道这个原因是什么,这就是我要问的原因:

  • 什么是Design> GenerateMember选项背后的基本原理?
  • 可以实现什么可以将此选项设置为false,而无法使用true实现?
  • 在什么情况下我应该保持将控件设置隐藏GenerateMember为false而不是让它具有默认值(true)?

谢谢.

c# windows-forms-designer visual-studio

5
推荐指数
1
解决办法
158
查看次数