microroom
microroom
洲者沧海之浮排,球者宇宙之尘埃,无海洋、太空科技之国无未来。
关注数: 132
粉丝数: 530
发帖数: 1,441
关注贴吧数: 146
五种方法实现全排列之方法五 <script> //栈+标记 function pailie5() { let arr=[1,2,3]; const len=arr.length; //[0,0]表示排列的第一个元素从数组下标为0的元素开始探测 let st=[[0,0]],selected=arr.map(_=>false),i,r=[]; let total=0; while(st.length>0) { [n,i]=st.pop(); if(i>0) selected[i-1]=false; for(;i<len;) { if(selected[i]==false) { //排列的第n+1个元素这次选择数组下标为i的元素 r[n]=arr[i]; if(n==len-1) { total++; document.write(`${r}<br />`); i++; } else { //将数组下标为i的元素设置为已选 selected[i]=true; //排列的第n+1个元素下次从数组下标为i+1的元素开始探测 st.push([n,i+1]); //排列的下一个元素从数组下标为0的元素开始探测 n++; i=0; } } else { i++; } } } document.write(`total5=${total}<br /><br />`); } pailie5(); </script>
五种方法实现全排列之方法四 <script> //递推+插入 let pailie4=()=> { let arr=[1,2,3]; let res1=[[arr[0]]]; for(let e of arr.slice(1)) { let res2=[]; for(let r of res1) { for(let i=0;i<=r.length;i++) { res2.push(r.slice(0,i).concat([e],r.slice(i))); } } res1=res2; } for(let r of res1) { document.write(`${r}<br />`); } document.write(`total4=${res1.length}<br /><br />`); }; pailie4(); </script>
五种方法实现全排列之方法三 <script> //递归+插入 let arr=[1,2,3]; let res=(function(n) { if(n==1) { return [[arr[0]]]; } else { let res1=arguments.callee(n-1); let res2=[]; for(let r of res1) { for(let i=0;i<=r.length;i++) { res2.push(r.slice(0,i).concat([arr[n-1]],r.slice(i))); } } return res2; } })(arr.length); for(let r of res) { document.write(`${r}<br />`); } document.write(`total3=${res.length}<br /><br />`); </script>
五种方法实现全排列之方法二 <script> //递归+标记 function pailie2() {let arr=[1,2,3]; const len=arr.length; let total=0; let selected=arr.map(_=>false); let res=[]; let f2=function(n) { if(n==len) { document.write(`${res}<br />`); total++; return; } for(let i=0;i<len;i++) { if(!selected[i]) { selected[i]=true; res[n]=arr[i]; f2(n+1); selected[i]=false; } } }; f2(0); document.write(`total2=${total}<br /><br />`); } pailie2(); </script>
五种方法实现全排列之方法一 <script> //递归+交换 function pailie1() { let arr=[1,2,3]; const len=arr.length; let total=0; function f1(start) { if(start==len) { document.write(`${arr}<br />`); total++; } for(let i=start;i<len;i++) { [arr[start],arr[i]]=[arr[i],arr[start]]; f1(start+1); [arr[start],arr[i]]=[arr[i],arr[start]]; } } f1(0); document.write(`total1=${total}<br /><br />`); } pailie1(); </script>
解包的使用
海象运算符与生成器 代码 g=((i,i**2) if i<5 else None for i in range(6)) while t:=next(g): print(t) def f(): for c in 'abcde': yield c yield None g=f() while c:=next(g): print(c) class gen: n,s=5,'一二三四五' def __init__(self): self.i=0 def __next__(self): r=gen.s[self.i] if self.i<gen.n else None self.i+=1 return r g=gen() while c:=next(g): print(c) 代码截图运行截图
输出、引用、可选参数,参数数组、匿名方法、lambda表达式 using System; using static System.Console; //定义委托类型时可以指定输出参数、引用参数、可选参数、参数数组 delegate void Del(out int a,ref int b,int c=77777,params int[] arr); class Exam { static void Main(string[] args) { int a=1,b=2; f(out a,ref b,555,6,7,8); f(out a,ref b); g(out a,ref b,999,6,7,8); g(out a,ref b); WriteLine("############"); Del d=f; d+=g; //可选参数c使用的也是定义委托Del时的默认值77777,未使用函数f和g的默认值, //参数数组为空 d(out a,ref b); b=112233; //匿名方法的参数不允许可选参数和参数数组 d+=delegate(out int a2,ref int b2,int c2/*=444*/,/*params*/ int[] arr2){ a2=123; WriteLine($"in delegate {a2},{b2},{c2},{String.Join("+",arr2)}"); }; //lambda表达式不允许有可选参数和参数数组 d+=(out int a3,ref int b3,int c3/*=444*/,/*params*/ int[] arr3)=>{ a3=456; WriteLine($"in lambda表达式 {a3},{b3},{c3},{String.Join("+",arr3)}"); }; d(out a,ref b,445566,8,8,8); b=666888; //可选参数c使用定义委托Del时的默认值77777,参数数组为空 d(out a,ref b); ReadKey(); } static void f(out int a,ref int b,int c=88,params int[] arr) { //输出参数使用前需赋值 a=111; WriteLine($"{a},{b}"); Action<int> d=delegate(int x) { WriteLine($"{c},{x}"); //匿名方法内部不能使用输出参数、引用参数 //WriteLine($"{a},{b}"); WriteLine($"{String.Join("+",arr)}"); }; Action<int> d2=(int x)=>{ WriteLine($"{c},{x}"); //lambda表达式内部不能使用输出参数、引用参数 //WriteLine($"{a},{b}"); WriteLine($"{String.Join("+",arr)}"); }; d(4); d2(44); } //输出参数、引用参数、参数数组不能指定默认值 //static void g(out int a=1,ref int b=2,params int[] arr=new int[]{5,6,7}) static void g(out int a,ref int b,int c=999,params int[] arr) { a=222; WriteLine($"{a},{b},{c},{String.Join("+",arr)}"); } }
Tuple与ValueTuple using System; using static System.Console; class Test { static void Main(string[] args) { Tuple<int, string, string> p = new Tuple <int, string, string>(1, "Steve", "Jobs"); WriteLine($"{p.Item1},{p.Item2},{p.Item3}"); var numbers = Tuple.Create(1, 2, 3, 4, 5, 6, 7, Tuple.Create(8, 9, 10, 11, 12, 13)); WriteLine($"{numbers.Item7}"); WriteLine($"{numbers.Rest}"); WriteLine($"{numbers.Rest.Item1}"); WriteLine($"{numbers.Rest.Item1.Item1}"); WriteLine($"{numbers.Rest.Item1.Item2}"); var num = Tuple.Create(1, 2, Tuple.Create(3, 4, 5, 6, 7, 8), 9, 10, 11, 12, 13 ); WriteLine($"{num.Item1}"); WriteLine($"{num.Item2}"); WriteLine($"{num.Item3}"); WriteLine($"{num.Item3.Item1}"); WriteLine($"{num.Rest}"); WriteLine($"{num.Rest.Item1}"); (int x,int y)=(6,8); (int i,string s,double d) t=(1,"aaa",1.2); var t2=("aa","bb"); var t3=(s1:"str1",s2:"str2"); WriteLine($"{x},{y}"); (x,y)=(y,x); WriteLine($"{x},{y}"); WriteLine($"{t.i},{t.s},{t.d}"); WriteLine($"{t2.GetType()},{t2.Item1},{t2.Item2}"); WriteLine($"{t3.s1},{t3.s2},{t3.Item1},{t3.Item2}"); (int n,char c)=f(("sss",111)); (int nn,char cc) vt1=f(("sss",111)); var vt2=f(("sss",111)); WriteLine($"{n},{c}"); WriteLine($"{vt1.nn},{vt1.cc}"); WriteLine($"{vt2.Item1},{vt2.Item2}"); ReadKey(); } static (int,char) f((string s,int i) t) { WriteLine($"{t.i},{t.s}"); return (i:123,s:'D'); } }
使用分部方法时的限制 分部方法只能位于分部类、分部结构、分部接口中,默认是私有的(分部接口中的默认是公共的)不能有访问权限修饰符,除了static不能有其它修饰符(abstract, extern, new, override, sealed, virtual),返回类型必须是void。 partial关键字只能出现在class、struct、interface、void的前面,静态分部方法只能写成static partial void。 代码: using static System.Console; partial class Program:I1 { static void Main() { P.M(); var o=new Program(); Program.sf(); o.f(); o.f1(); o.f2(); o.f4(); o.f5(); ReadKey(); } partial void f(); static partial void sf() { WriteLine("static partial void sf()"); } public void f1() {WriteLine("public void f1()");} public virtual void f4() {WriteLine("public virtual void f4()");} } partial class Program { partial void f() { WriteLine("partial void f()"); } static partial void sf(); public virtual void f2() {WriteLine("public virtual void f2()");} public void f5() {WriteLine("public void f5()");} } class P { internal static void M() { /* var o=new Program(); //分部方法默认是私有的 Program.sf(); o.f(); */ } } partial interface I1 { partial void f1(); void f2(); //abstract void f3(); } partial interface I1 { partial void f4(); void f5(); }
使用结构时的限制 结构: 1 不能有显式无参构造函数,不能有析构函数 2 不能继承自其它结构或类,不能被其它结构或类继承 3 构造函数中必须初始化所有实例字段,实例字段、实例属性不能在类中初始化,未调用构造函数时,实例字段的值是不确定的,使用某个实例字段前必须为实例字段赋值,不能通过实例引用访问静态成员 4 不能包含抽象、密封、虚方法,不能包含保护成员 5 字段默认是私有的 using static System.Console; public class Test { static void Main() { Point p; //未调用构造函数时,字段的值是不确定的,使用字段前必须赋值 p.x=11; p.y=22; //p.st=8; //p.sf(); Point.st=9; Point.sf(); WriteLine($"{p.x},{p.y},{Point.st}"); WriteLine("ok"); } } struct Shape { public Shape(int n) { WriteLine("public Shape(int n)"); } } struct Point //struct Point:Shape //xxx { public Point(int x=0,int y=2) { //必须初始化所有实例字段 this.x=1; this.y=y; st=6; } /* //xxx public Point() { x=y=0; } public abstract void af() {} public sealed void sf() {} public virtual void vf() {} ~Point(){} protected void pf() { WriteLine($"protected void pf() z={z}"); } protected int z; */ static Point(){WriteLine("static Point()");st=7;} public static void sf() {WriteLine("public static void sf()");} //默认私有 public int x,y; //不能初始化实例字段 //public int y=0; //会默认初始化为0 public static int st; } //struct Point2D:Point{} //xxx
动态类型与匿名类型 using static System.Console; public class Test { static void Main() { //匿名类型数组 dynamic a=new[] { new {id=1,name="a",date=new {y=1,m=1,d=1}/*嵌套匿名类型*/}, new {id=666,name="ccc",date=new {y=6,m=6,d=6}}, new {id=2,name="bb",date=new {y=2,m=2,d=2}}, }; foreach(dynamic o in a) { WriteLine($"{o.id},{o.name},{o.date.y},{o.date.m},{o.date.d}"); } a=1; switch((int)a) { case 1:case 2: WriteLine("1或2"); goto case 4; case 3: WriteLine("3"); break; case 4: a="ok"; WriteLine($"{a}\n4"); return; } } }
选择排序、鸡尾酒排序、冒泡排序 using System; using System.Linq; class P { static void Main() { const int Min=6,Max=21; var R=new Random(); var arr=Enumerable.Range(Min,Max-Min+1).ToArray(); Action<int[]> Rand=(int[] a)=>{ for(int i=0,j,t;i<a.Length;i++) { j=R.Next(0,Max-Min+1); t=a[i]; a[i]=arr[j]; a[j]=t; } }; Action<int[]> Print=(int[] a)=>{ Array.ForEach(a,e=>Console.Write("{0},",e)); Console.WriteLine(); }; Action<string,Action<int[]>> Sort=(string msg,Action<int[]> ac)=>{ int[] dst=new int[arr.Length]; Array.Copy(arr,dst,arr.Length); Console.WriteLine("{0}前:",msg); Print(dst); ac(dst); Console.WriteLine("{0}后:",msg); Print(dst); Console.WriteLine(); }; Rand(arr); Sort("选择排序",SelectSort); Sort("鸡尾酒排序",CocktailSort); Sort("冒泡排序1",BubbleSort1); Sort("冒泡排序2",BubbleSort2); Console.Write("按任意键继续。。。"); Console.ReadKey(true); } static void Swap<T>(ref T a,ref T b) { T x=a; a=b; b=x; } //选择排序 static void SelectSort(params int[] arr) { int a; for(int i=0;i<arr.Length-1;i++) { a=i; for(int j=i+1;j<arr.Length;j++) if(arr[j]<arr[a]) a=j; if(a!=i) { Swap(ref arr[i],ref arr[a]); } } } //鸡尾酒排序 static void CocktailSort(params int[] arr) { int a,b; for(int i=0,j=arr.Length-1;i<j;i++,j--) { a=b=i; for(int k=i;k<=j;k++) { if(arr[k]<arr[a]) a=k; else if(arr[k]>arr[b]) b=k; } if(a!=i) { Swap(ref arr[i],ref arr[a]); if(b==i) b=a; } if(b!=j) { Swap(ref arr[j],ref arr[b]); } } } //冒泡排序1 static void BubbleSort1(params int[] arr) { int a=0; bool sw=true; while(sw) { sw=false; for(int i=arr.Length-1;i>=a+1;i--) { //小数上浮 if(arr[i]<arr[i-1]) { Swap(ref arr[i],ref arr[i-1]); sw=true; } } a++; } } //冒泡排序2 static void BubbleSort2(params int[] arr) { bool sw=true; for(int i=0;sw&&i<arr.Length-1;i++) { sw=false; for(int j=0;j<arr.Length-1-i;j++) { //大数下沉 if(arr[j]>arr[j+1]) { Swap(ref arr[j],ref arr[j+1]); sw=true; } } } } }
快速排序的3种实现方法 import java.util.*; import static java.lang.System.*; import java.util.stream.*; import java.util.function.*; public class Program { public static void main(String[] args) { final int Count=81,Max=51; int[] arr=new int[Count]; Random r=new Random(); Arrays.setAll(arr,(int operand)->r.nextInt(Max)); int[] arr1=Arrays.copyOf(arr,Count); qsort1(arr1,0,Count-1); out.println("qsort1排序后:"); IntStream.of(arr1).forEach(e->out.printf("%d,",e)); out.println(); int[] arr2=Arrays.copyOf(arr,Count); qsort2(arr2,0,Count-1); out.println("qsort2排序后:"); Arrays.stream(arr2).forEach(e->out.printf("%d,",e)); out.println(); int[] arr3=Arrays.copyOf(arr,Count); qsort3(arr3,0,Count-1); out.println("qsort3排序后:"); Arrays.stream(arr3).forEach(e->out.printf("%d,",e)); out.println(); out.println("原数组:"); IntStream.of(arr).forEach(e->out.printf("%d,",e)); out.println(); Arrays.sort(arr); out.println("调用类库方法Arrays.sort对原数组排序后:"); IntStream.of(arr).forEach(e->out.printf("%d,",e)); out.println(); boolean eq=true; int[][] arrs={arr1,arr2,arr3}; for(int i=0;eq&&i<arrs.length;i++) { eq=Arrays.equals(arr,arrs[i]); } out.printf("4个排序后的数组相等?%b%n",eq); } //3个while版 static void qsort1(int[] arr,int l,int r) { int p,l2=l,r2=r; if(l>=r) return; p=arr[l]; while(l<r) { while(l<r&&arr[r]>p) r--; arr[l]=arr[r]; while(l<r&&arr[l]<=p) l++; arr[r]=arr[l]; } arr[l]=p; qsort1(arr,l2,l-1); qsort1(arr,l+1,r2); } //一个for版 static void qsort2(int[] arr,int l,int r) { int s,t; if(l>=r) return; s=l; for(int i=l+1;i<=r;i++) { if(arr[i]<arr[l]) { s++; t=arr[s]; arr[s]=arr[i]; arr[i]=t; } } t=arr[l]; arr[l]=arr[s]; arr[s]=t; qsort2(arr,l,s-1); qsort2(arr,s+1,r); } //非递归版 static void qsort3(int[] arr,int l,int r) { Deque<int[]> stack; int[] lr; int s,t; if(l>=r) return; stack=new ArrayDeque<>(); stack.push(new int[] {l,r}); while(!stack.isEmpty()) { lr=stack.pop(); l=lr[0]; r=lr[1]; s=l; for(int i=l+1;i<=r;i++) { if(arr[i]<arr[l]) { s++; t=arr[s]; arr[s]=arr[i]; arr[i]=t; } } t=arr[l]; arr[l]=arr[s]; arr[s]=t; if(l<s-1) stack.push(new int[] {l,s-1}); if(s+1<r) stack.push(new int[] {s+1,r}); } } }
实现接口的方法和属性 1 用类实现接口的属性可以添加额外的访问器,用显式接口成员实现不能添加额外的访问器。 2 显式接口成员实现的方法和属性只能通过接口的引用变量来访问。 3 可同时用类和显式接口成员实现来实现接口的方法和属性。 例子: using System; class Program : I1 { internal Program(){i3=1234;} //类实现f1 public void f1() { Console.WriteLine("f1"); } //显式接口成员实现I1.f2 void I1.f2() { Console.WriteLine("I1.f2"); } //同时类实现、显式接口成员实现f3 public void f3() { Console.WriteLine("f3"); } void I1.f3() { Console.WriteLine("I1.f3"); } //类实现属性p1可添加额外的访问器set public int p1 { get;set; } //显式接口成员实现属性p2不能添加额外的访问器set int I1.p2 { get; //错误 //set; } int i3; //同时类实现、显式接口成员实现属性p3 public int p3 {get;set;} int I1.p3 { get{return i3;} //错误,显式接口成员实现时不能添加额外的访问器set //set{i3=value;} } static void Main() { var o=new Program(); I1 i=o; o.f1(); o.p1=1; int p1=o.p1; //错误,f2、p2是通过显式接口成员实现的,不能通过类的引用变量调用 //o.f2(); //int a=o.p2; //正确,通过接口的引用变量调用显式接口成员实现的函数、属性 i.f2(); int b=i.p2; //正确,同时类实现、显式接口成员实现了f3、p3 o.f3(); o.p3=3; int c1=o.p3; i.f3(); //错误,显式接口成员实现的没有set访问器 //i.p3=33; int c2=i.p3; Console.WriteLine("end"); Console.ReadKey(); } } interface I1 { void f1(); void f2(); void f3(); int p1{get;} int p2{get;} int p3{get;} }
吧友的一个推理题2 题: 八粒药丸有一粒变质了,称三次找出并判断轻重。 解:
吧友的一个推理题 题目:解:
随机点名小程序 源码截图:运行截图:
重载*(解引用)、()(函数调用)、->(间接成员访问)(二) 例子: 将*重载为友元函数,->重载函数返回一个重载了->的结构体变量的引用。 #include <iostream> using namespace std; struct stru { stru(string s="结构体stru"):s(s) {} stru* operator->() { return this; } string s; }; class Integer { Integer(int x=666) { p=new int{x}; } ~Integer() { if(p) delete p; if(ps) delete ps; } friend int operator*(Integer &i); stru& operator->() { return *ps; } friend int main(); int *p=nullptr; stru *ps=new stru; }; int operator*(Integer &i) { return *i.p; } int main() { Integer i,i2(12345); cout<<*i<<endl; cout<<*i2<<endl; cout<<i->s<<endl; i2->s="结构体stru的成员s"; cout<<i2->s<<endl; return 0; }
重载*(解引用)、()(函数调用)、->(间接成员访问)(一) 1 *可以重载为非静态成员函数或友元函数,()、->只能重载为非静态成员函数。 2 ->重载函数可以返回一个指向结构体变量或类对象的指针,也可以返回一个重载了->的结构体变量或重载了->的类对象。 例子: 将*重载为实例成员函数,->返回指针。 #include <iostream> using namespace std; struct stru { stru(string s="结构体stru"):s(s) {} string s; }; class Integer { Integer(int x=666) { p=new int{x}; } ~Integer() { if(p) delete p; if(ps) delete ps; } int operator*() { return *p; } int operator()(string s="重载()") { cout<<s<<endl; return **this; } stru* operator->() { return ps; } friend int main(); int *p=nullptr; stru *ps=new stru; }; int main() { Integer i,i2(12345); cout<<*i<<endl; cout<<*i2<<endl; cout<<i()<<endl; cout<<i2("i2")<<endl; cout<<i->s<<endl; i2->s="结构体stru的成员s"; cout<<i2->s<<endl; return 0; }
父子互为友元类以及main同时为父子的友元函数 父类是子类的友元类的同时,子类也可以是父类的友元类,main也可以同时是父类子类的友元函数。 例子: #include <iostream> using namespace std; class A { private: int a=123; friend class B; friend int main(); void f(); }; class B : private A { private: void f() { cout<<"B::f()"<<endl; cout<<A::a<<endl; cout<<a<<endl; } friend class A; friend int main(); int a=456; }; void A::f() { cout<<"A::f()"<<endl; B b; b.f(); } int main() { A().f(); B().f(); return 0; }
python的//和% 1 //是取整运算(即求商),结果是向负无穷大方向(即数轴的负方向)取整,所以,-1//100000=-1,这是因为-1/100000=-0.000010,而-0.000010向负无穷大方向取整后就是-1。 2 %是求余运算,计算公式是:被除数-除数*商,所以,-1%100000=-1-100000*(-1)=-1+100000=99999。 验证用例子: print('-1/100000=%f' %(-1/100000)) print(f'-1//100000={-1//100000}') print(f'-1%100000={-1%100000}') 运行截图:一个解密算法,用到了%的特性: print(''.join(chr(d%100000) for d in (-74895,-69660,-99887,-99887,-99950,-99946,-99952,-99944,-99951,-99951,-99949,-99946,-99949,-99949))) 运行截图: 有违规内容,不能截图。
模块与类型提升 模块中的: 1 数据成员都默认是Private(可指定)和Shared的,函数成员都默认是Public(可指定)和Shared的,类型成员都默认是Public(可指定)的。 2 非Private成员会类型提升到包围它的名字空间中。 3 成员不能声明为Protected。 例子: Option Explicit On Option Strict On Imports Microsoft{.}VisualBasic Imports System{.}Console Namespace ns Friend Module m Dim a As Integer=666 'Protected b As Integer=777 'xxx Friend c%=888 Public d%=999 Const const_e%=5555 Friend Const fc%=123 Class Cls End Class Private Class PriCls End Class 'Protected Class ProCls 'xxx ' 'End Class Sub f() writeline("sub ns.m.f") End Sub Private Sub PriF() End Sub 'Protected Sub ProF() 'xxx ' 'End Sub End Module End Namespace Module m2 Friend m2a%=1122 Sub m2f() writeline("sub m2.m2f") End Sub Class m2Cls End Class End Module Module Program Sub Main() '输出 '123 'sub ns.m.f '1122 'sub m2.m2f writeline(ns.fc) Dim o As New ns{.}Cls ns.f() writeline(m2a) m2f() Dim o2 As New m2Cls writeline Write("Press any key to continue . . . ") readkey(True) End Sub End Module 说明: 代码中的{.}都要转换成.。
访问被子类隐藏的父类成员的方法2 当子类定义了与父类同名的成员时,父类的所有同名成员在子类中都会被隐藏,除了可以通过作用域限定符来访问这些被隐藏的成员,也可以使用using来引入这些被隐藏的成员。 1 using只能引入被子类函数成员隐藏的父类成员。 2 对于从父类继承的成员,使用using还可以重新指定访问权限修饰符。 例子: #include <iostream> using namespace std; class A { public: void fa(){} void fa(int){} static void sfa(){} static void sfa(int){} int ia=1; static int sia; class ca{}; int x; void y(){} }; int A::sia=1; class B : public A { public: using A::fa; using A::sfa; // //错误,被子类数据成员隐藏的父类成员不可引入 //int x,y; //using A::x; //using A::y; // /// ///被子类函数成员隐藏的父类成员可以引入 void x(){} void y(){} using A::x; using A::y; /// private: // //对于从父类继承的成员可以重新指定访问权限修饰符 using A::ia; using A::sia; using A::ca; // static void fa(string) { sia=22; ca o; } void sfa(string) { ia=22; ca o; } }; int main() { B b; b.fa();b.fa(1);b.sfa();b.sfa(1); // //错误,这些成员在子类中都成了私有的 //int i=b.sia;i=B::sia;i=b.ia; //B::ca o; // cout<<b.A::sia<<endl; cout<<A::sia<<endl; cout<<b.A::ia<<endl; B::A::ca o2; A::ca o3; return 0; }
访问被子类隐藏的父类成员的方法1 当子类定义了与父类同名的成员时,父类的所有同名成员在子类中都会被隐藏,可以通过作用域限定符来访问这些被隐藏的成员。 例子: #include <iostream> using namespace std; class A { public: void fa(){} void fa(int){} static void sfa(){} static void sfa(int){} int ia=1; static int sia; class ca{}; }; int A::sia=1; class B : public A { public: void ia(){} void sia(){} char fa='A',sfa='B'; static char ca; }; char B::ca='C'; int main() { B b; string s; // //错误,因为这些成员都被子类隐藏了 //b.fa();b.fa(1);b.sfa();b.sfa(1); //int ia=b.ia,sia=b.sia; //B::ca oca; // /// ///使用作用域限定符访问隐藏的成员 b.A::fa();b.A::fa(1);b.A::sfa();b.A::sfa(1); int ia=b.A::ia,sia=b.A::sia; B::A::ca oca; /// // //当然,访问父类的静态成员或嵌套定义的类型总是可以通过加A::前缀实现,而不受隐藏的影响 A::sfa();A::sfa(1); sia=A::sia; A::ca oca2; // /// ///正常访问子类的成员 b.ia();b.sia(); s=s+b.fa+b.sfa+b.ca; /// cout<<s<<endl; return 0; }
指针修改常量的值后,再直接、通过指针、通过引用输出的区别 常量的值通过指针修改后,直接通过常量输出的是原来的值(因为编译器在所有使用常量的地方用其值进行了替换,类似于宏替换),而通过指针和引用输出的是修改后的值。 例子: #include <iostream> using namespace std; int main() { int x; const int ci=12; const int &clr1=ci; auto &clr2=ci; auto &clr3=clr1; decltype((ci)) clr4=ci; decltype(clr1) clr5=clr4; *(int*)&ci=999; /* 错误,因为都是常量左值引用 clr1=777;clr2=777; clr3=777;clr4=777;clr5=777; */ cout<<"ci="<<ci<<endl; cout<<"*&ci="<<*&ci<<endl; cout<<"clr1="<<clr1<<endl; cout<<"clr2="<<clr2<<endl; cout<<"clr3="<<clr3<<endl; cout<<"clr4="<<clr4<<endl; cout<<"clr5="<<clr5<<endl; return 0; }
用/和*指定参数的传递方式 1 /使前面的所有参数只能作为位置参数传递。 2 *使后面的所有参数只能作为关键字参数传递。 3 如果未明确指定参数的传递方式,只需保证关键字传参在所有位置传参的后面。 例子: def f(a,b,/,*,c,d):pass def g(a,b,/):pass def h(*,a,b):pass def i(a,b):pass #a、b只能作为位置参数传递 #c、d只能作为关键字参数传递 f(1,2,c=3,d=4) #a、b只能作为位置参数传递 g(1,2) #a、b只能作为关键字参数传递 h(a=1,b=2) #只需保证所有关键字传参都位于位置传参 #的后面 i(1,2) i(1,b=2) i(a=1,b=2) print('end')
null与undefined的区别 1 null的类型是object,而undefined 的类型是undefined(一种特殊的类型,这种类型的对象只有一个即undefined) 2 null与undefined相等(==),但不等同(===),因为类型不同 3 null和undefined转换为布尔类型都为false,但它们都既不等于true也不等于false 例子: console.log(typeof null); console.log(typeof undefined); console.log(); console.log(null==undefined); console.log(null===undefined); console.log(); console.log(null!=true); console.log(null!=false); console.log(null!==true); console.log(null!==false); console.log(); console.log(undefined!=true); console.log(undefined!=false); console.log(undefined!==true); console.log(undefined!==false); console.log(); if(!null && !undefined) console.log('null和undefined转换为布尔类型都为false');
关于构造函数是否一定要返回this 当函数作为构造函数使用时,默认是返回当前创建的对象的引用(即this),其实可以返回其它引用。 例子: let p; function Person(nm,a) { this.name=nm; this.age=a; p=this; return new Student('AAA',16,99); } function Student(nm,a,score) { this.name=nm; this.age=a; this.score=score; } let s=new Person('zhs',28); console.log(p); console.log(s);
关于函数作为普通函数、构造函数调用时,this引用的区别 作为普通函数调用时,this引用的是全局对象;作为构造函数调用时,this引用的是当前创建的对象。 例子:
关于arguments.callee在匿名函数中的使用 匿名函数执行时也有arguments,可以利用arguments.callee递归调用匿名函数。 例子: console.log(function(n) { return n==1?1:n+arguments.callee(n-1); }(10));
1
下一页