继续在 C++ error: base function is protected 中学到的东西...
C++11 指向成员的指针规则有效地去除了任何值的 protected 关键字,因为可以在不相关的类中访问 protected 成员,而无需任何邪恶/不安全的强制转换。
也就是说:
class Encapsulator
{
protected:
int i;
public:
Encapsulator(int v) : i(v) {}
};
Encapsulator f(int x) { return x + 2; }
#include <iostream>
int main(void)
{
Encapsulator e = f(7);
// forbidden: std::cout << e.i << std::endl; because i is protected
// forbidden: int Encapsulator::*pi = &Encapsulator::i; because i is protected
// forbidden: struct Gimme : Encapsulator { static int read(Encapsulator& o) { return o.i; } };
// loophole:
struct Gimme : Encapsulator { static int Encapsulator::* it() { return &Gimme::i; } };
int Encapsulator::*pi = Gimme::it();
std::cout << e.*pi << std::endl;
}
这真的符合标准吗?
(我认为这是一个缺陷,并声称 &Gimme::i 的类型确实应该是 int Gimme::* 即使 i 是基类的成员。但我在标准中没有看到任何使其如此的东西,并且有一个非常具体的示例显示了这一点。)
我意识到有些人可能会惊讶于第三种评论方法(第二个 ideone 测试用例)实际上失败了。那是因为思考 protected 正确方法不是“我的派生类可以访问,而没有其他人”,而是“如果您从我那里派生,您将可以访问您的实例中包含的这些继承变量,除非您授予它”。例如,如果 Button 继承 Control,则 Button 实例中的 Control 的 protected 成员只能由 Control 和 Button,以及(假设 Button 不禁止它)实例的实际动态类型和任何中间基。
这个漏洞颠覆了契约(Contract),完全违背了11.4p1的精神:
An additional access check beyond those described earlier in Clause 11 is applied when a non-static data member or non-static member function is a protected member of its naming class. As described earlier, access to a protected member is granted because the reference occurs in a friend or member of some class
C. If the access is to form a pointer to member (5.3.1), the nested-name-specifier shall denoteCor a class derived fromC. All other accesses involve a (possibly implicit) object expression. In this case, the class of the object expression shall beCor a class derived fromC.
感谢 AndreyT 提供链接 http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#203它提供了激发变革的更多示例,并呼吁演进工作组提出这个问题。
最佳答案
我已经看到了这种技术,我称之为“ protected 黑客”,在这里和其他地方多次提到。是的,这种行为是正确的,而且它确实是一种合法的方式来规避 protected 访问,而无需诉诸任何“肮脏”的黑客攻击。
当 m 是类 Base 的成员时,使 &Derived::m 表达式产生 指针的问题>Derived::* 类型是类成员指针是逆变,而不是协变。它会使生成的指针无法与 Base 对象一起使用。比如这段代码编译
struct Base { int m; };
struct Derived : Base {};
int main() {
int Base::*p = &Derived::m; // <- 1
Base b;
b.*p = 42; // <- 2
}
因为 &Derived::m 产生一个 int Base::* 值。如果它产生一个 int Derived::* 值,代码将在第 1 行编译失败。如果我们尝试用
int Derived::*p = &Derived::m; // <- 1
它将无法在第 2 行编译。使其编译的唯一方法是执行强制转换
b.*static_cast<int Base::*>(p) = 42; // <- 2
这不好。
附:我同意,这不是一个非常有说服力的例子(“从一开始就使用 &Base:m 问题就解决了”)。但是,http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#203有更多信息可以解释为什么最初做出这样的决定。他们说
Notes from 04/00 meeting:
The rationale for the current treatment is to permit the widest possible use to be made of a given address-of-member expression. Since a pointer-to-base-member can be implicitly converted to a pointer-to-derived-member, making the type of the expression a pointer-to-base-member allows the result to initialize or be assigned to either a pointer-to-base-member or a pointer-to-derived-member. Accepting this proposal would allow only the latter use.
关于c++ - 在 C++11 中, protected 意味着公共(public)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16971897/
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
protect_from_forgery默认Rails6应用程序不包含在我的应用程序Controller中,但是有嵌入式ruby在主应用程序布局中。这是否意味着protect_from_forgery方法已经被抽象并且在应用程序Controller中不再明确需要?我买了实用程序员的Rails6一书,我唯一能找到的是“csrf_meta_tags()方法设置了防止跨站点请求伪造攻击所需的所有幕后数据”。 最佳答案 对于rails5.2和更高版本,默认情况下在ActionController::Base上启用。查看此提交:https
我不知道为什么,但是当我设置这个设置时它无法编译设置:static_cache_control,[:public,:max_age=>300]这是我得到的syntaxerror,unexpectedtASSOC,expecting']'(SyntaxError)set:static_cache_control,[:public,:max_age=>300]^我只想将“过期”header设置为css、javaascript和图像文件。谢谢。 最佳答案 我猜您使用的是Ruby1.8.7。Sinatra文档中显示的语法似乎是在Ruby1.
如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:
运行bundleinstall后出现此错误:Gem::Package::FormatError:nometadatafoundin/Users/jeanosorio/.rvm/gems/ruby-1.9.3-p286/cache/libv8-3.11.8.13-x86_64-darwin-12.gemAnerroroccurredwhileinstallinglibv8(3.11.8.13),andBundlercannotcontinue.Makesurethat`geminstalllibv8-v'3.11.8.13'`succeedsbeforebundling.我试试gemin
假设我有一个在Ruby中看起来像这样的哈希:{:ie0=>"Hi",:ex0=>"Hey",:eg0=>"Howdy",:ie1=>"Hello",:ex1=>"Greetings",:eg1=>"Goodday"}有什么好的方法可以将它变成如下内容:{"0"=>{"ie"=>"Hi","ex"=>"Hey","eg"=>"Howdy"},"1"=>{"ie"=>"Hello","ex"=>"Greetings","eg"=>"Goodday"}} 最佳答案 您要求一个好的方法来做到这一点,所以答案是:一种您或同事可以在六个月后理解
我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我
在ruby中,你可以这样做:classThingpublicdeff1puts"f1"endprivatedeff2puts"f2"endpublicdeff3puts"f3"endprivatedeff4puts"f4"endend现在f1和f3是公共(public)的,f2和f4是私有(private)的。内部发生了什么,允许您调用一个类方法,然后更改方法定义?我怎样才能实现相同的功能(表面上是创建我自己的java之类的注释)例如...classThingfundeff1puts"hey"endnotfundeff2puts"hey"endendfun和notfun将更改以下函数定
我有一个数组数组,想将元素附加到子数组。+=做我想做的,但我想了解为什么push不做。我期望的行为(并与+=一起工作):b=Array.new(3,[])b[0]+=["apple"]b[1]+=["orange"]b[2]+=["frog"]b=>[["苹果"],["橙子"],["Frog"]]通过推送,我将推送的元素附加到每个子数组(为什么?):a=Array.new(3,[])a[0].push("apple")a[1].push("orange")a[2].push("frog")a=>[[“苹果”、“橙子”、“Frog”]、[“苹果”、“橙子”、“Frog”]、[“苹果”、“